【牛客 - 371牛客OI周赛7-提高组B】小睿睿的询问(RMQ,ST表维护下标)
生活随笔
收集整理的這篇文章主要介紹了
【牛客 - 371牛客OI周赛7-提高组B】小睿睿的询问(RMQ,ST表维护下标)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題干:
鏈接:https://ac.nowcoder.com/acm/contest/371/B
來源:牛客網
?
小睿睿的n個妹紙排成一排,每個妹紙有一個顏值val[i]。有m個詢問,對于每一個詢問,小睿睿想知道區間[L,R]顏值最高而編號最小的妹紙是哪一個
對于妹紙們的顏值val[i],其生成函數為:
void generate_array(int n,int seed) {unsigned x = seed;for (int i=1;i<=n;++i){x ^= x << 13;x ^= x >> 17;x ^= x << 5;val[i]=x%100;} }對于每一組詢問,區間[L,R]的生成函數為:
void generate_ask(int n,int m,int seedx,int seedy) {unsigned x=seedx,y=seedy;for (int i=1;i<=m;++i){x ^= x << 13;x ^= x >> 17;x ^= x << 5;y ^= y << 13;y ^= y >> 17;y ^= y << 5;L=(x^lastans)%n+1,R=(y^lastans)%n+1;if (L>R)swap(L,R);//解決詢問} }?
其中lastans為上個詢問的答案,對于第一個詢問,lastans為0
輸入描述:
第1行2個整數n,m,分別表示序列長度和詢問次數第2行3個整數seed,seedx,seedy,意義如題所示輸出描述:
一行一個整數,表示所有詢問的答案的異或和示例1
輸入
復制
10 5 3 5 7輸出
復制
2說明
生成序列:7 11 47 53 3 7 63 36 55 55各組詢問及答案:詢問:4 6該詢問答案:4詢問:2 6該詢問答案:4詢問:2 2該詢問答案:2詢問:4 8該詢問答案:7詢問:1 9該詢問答案:7所有詢問的答案的異或和:2示例2
輸入
復制
100000 10000000 1 2 3輸出
復制
5042備注:
對于30%的數據,n,m<=1000對于50%的數據,m<=1000000對于100%的數據,n<=100000,m<=10000000,seedx,seedy,seed<=1000解題報告:
? ?跟一般的ST表不同,這里的ST表不是維護一個最大值,而是維護最大值所對應的下標,因為題目中說要維護的答案是下標,如果有多個最大值的話返回左邊的下標。而通過ST表的原理我們不難得出結論,對于下標也同樣可以維護。
AC代碼:
#include<cstdio> #include<assert.h> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<ctime> #include<string> #include<cmath> #include<cstring> #define ll long long #define fi first #define se second #define pb push_back #define pm make_pair using namespace std; const int MAX = 6e5 + 6; int lastans = 0; int seed,seedx,seedy,n,m; int val[MAX],Log[MAX]; int dp[MAX][25]; void generate_array(int n,int seed) {unsigned x = seed;for (int i=1; i<=n; ++i) {x ^= x << 13;x ^= x >> 17;x ^= x << 5;val[i]=x%100;} } inline int fff(int x,int y) {if(val[x] < val[y]) return y;if(val[x] > val[y]) return x;return x<y ? x : y; } int cal(int l,int r) {int k = Log[r-l+1];return fff(dp[l][k],dp[r- (1<<k) + 1][k]); } int generate_ask(int n,int m,int seedx,int seedy) {unsigned x=seedx,y=seedy;int L,R;int ans = 0;for (int i=1; i<=m; ++i) {x ^= x << 13;x ^= x >> 17;x ^= x << 5;y ^= y << 13;y ^= y >> 17;y ^= y << 5;L=(x^lastans)%n+1,R=(y^lastans)%n+1;if (L>R)swap(L,R);//解決詢問lastans = cal(L,R);ans ^= lastans ;}return ans; } void init() {for(int i = 1; i<=n; i++) dp[i][0] = i;for(int j = 1; (1<<j) <= n; j++) {for(int i = 1; i<=n; i++) {//枚舉數字dp[i][j] = fff(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);}}//找到小于等于i的那個二進制for(int i = 1; i<=n; i++) {int k = 0;while((1<<(k+1)) <= i) k++;Log[i] = k;}} int main() {cin>>n>>m>>seed>>seedx>>seedy;int ST = clock();int ans = 0;generate_array(n,seed);init();cout << generate_ask(n,m,seedx,seedy) << endl;return 0 ; }?
總結
以上是生活随笔為你收集整理的【牛客 - 371牛客OI周赛7-提高组B】小睿睿的询问(RMQ,ST表维护下标)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 马斯克:美国或跟日本一样 不解决生育问题
- 下一篇: 【POJ - 3020】Antenna