Codeforces Round #223 (Div. 2): C. Sereja and Prefixes(二分+遞迴)
阿新 • • 發佈:2018-12-18
題意:
你有一個序列,一開始為空,之後進行m次操作,操作有兩種:
- 1 x:在當前序列後面新增一個數x
- 2 x, y:將序列的前x個數複製y遍接序列後面(x<10000)
之後n次詢問,每次詢問位置p上面的數字是多少,保證p不超過序列長度
思路:
對於每次詢問,直接暴力遞迴當前位置上的數字是哪次操作①新增的就行了,因為複製操作每次只會複製前10000個數字,所以遞迴次數不會超過15次(遞迴時可能需要用到二分)
當然也可以直接記下來前10000個數字是多少, 這樣應該就是線性的了
#include<stdio.h> #include<string.h> #include<algorithm> #include<map> #include<string> #include<math.h> #include<queue> #include<stack> #include<iostream> using namespace std; #define LL long long #define mod 1000000007 typedef struct Res { int op; int x, y; LL l, r; }Res; Res s[200005]; int Gao(int p, LL x) { int l, r, m; if(s[p].op==1) return s[p].x; else { r = x-s[p].l+1; x = (r-1)%s[p].x+1; l = 1, r = p-1; while(l<r) { m = (l+r+1)/2; if(x<s[m].l) r = m-1; else l = m; } return Gao(r, x); } } int main(void) { LL now, p; int m, n, i, R; scanf("%d", &m); for(i=1;i<=m;i++) { scanf("%d", &s[i].op); if(s[i].op==1) scanf("%d", &s[i].x); else scanf("%d%d", &s[i].x, &s[i].y); } R = now = 0; scanf("%d", &n); for(i=1;i<=n;i++) { scanf("%lld", &p); while(R!=m && p>now) { R++; s[R].l = now+1; if(s[R].op==1) s[R].r = s[R].l; else s[R].r = s[R].x*s[R].y+now; now = s[R].r; } printf("%d ", Gao(R, p)); } puts(""); return 0; }