NOIP2020.9.19模擬patrick
阿新 • • 發佈:2020-09-19
題目大意
動態維護數列中大於等於某個數的極長連續段的個數。
解題思路
\(Code\)
#include<cstdio> using namespace std; long long f[2000005],a[500005],tag[2000005],ans,n,m; void pushdown(int l,int r,int k) { if (!tag[k]) return; int mid = l + r >> 1; tag[k << 1] += tag[k]; tag[k << 1 | 1] += tag[k]; f[k << 1] += tag[k] * (mid - l + 1); f[k << 1 | 1] += tag[k] * (r - mid); tag[k] = 0; } void change(int l,int r,int k,int L,int R,int u) { if (r < L && l > R) return; if (l >= L && r <= R) { f[k] += u * (r - l + 1); tag[k] += u; return; } pushdown(l,r,k); int mid = l + r >> 1; if (L <= mid) change(l,mid,k << 1,L,R,u); if (R > mid) change(mid + 1,r,k << 1 | 1,L,R,u); f[k] = f[k << 1] + f[k << 1 | 1]; } int query(int l,int r,int k,int u) { if (l == r && l == u) return f[k]; pushdown(l,r,k); int mid = l + r >> 1; if (u <= mid) return query(l,mid,k << 1,u); else return query(mid + 1,r,k << 1 | 1,u); } int main() { scanf("%d%d",&n,&m); for (int i = 1; i <= n; i++) { scanf("%d",&a[i]); if (a[i] > 500000) a[i] = 500000; if (a[i] > a[i - 1]) change(1,500000,1,a[i - 1] + 1,a[i],1); } char s[5]; int lst = 0; for (int i = 1; i <= m; i++) { int q,p; scanf("%s",s); if (s[0] == 'Q') { scanf("%d",&q); q = q ^ lst; lst = query(1,500000,1,q); printf("%d\n",lst); } else { scanf("%d%d",&q,&p); q = q ^ lst,p = p ^ lst; if (a[q] < a[q + 1]) change(1,500000,1,a[q] + 1,a[q + 1],-1); if (p < a[q + 1]) change(1,500000,1,p + 1,a[q + 1],1); if (a[q] > a[q - 1]) change(1,500000,1,a[q - 1] + 1,a[q],-1); if (p > a[q - 1]) change(1,500000,1,a[q - 1] + 1,p,1); a[q] = p; } } }