题目大意:给定一个序列,多次求区间内逆序对个数 强制在线
让我们呐喊一声:出题人卡常数丧心病狂!
再来一次:出题人卡常数丧心病狂!!!!
不强制在线的直接莫队就能搞 强制在线我是跪了QTZ
首先看这数据范围肯定O(n√nlogn)了
我们分块 令cnt[i][j]为从第i块的开头起到第j个点这段区间的逆序对数
这个用树状数组就可以O(n√nlogn)搞出来 我一开始直接用可持久化线段树搞这部分 常数大TLE到死啊
然后对于每次查询,如果左右端点在同一块直接树状数组暴力,如果左右端点在不同一块的话 令temp为x所在块的下一块的左端点
对于[temp,y]部分的逆序对已经预处理出来了,直接调用即可
对于[x,temp-1]部分的逆序对,我们对于[x,temp-1]的每一个a[i]求出[i+1,y]区间内有多少比a[i]小的数,这个用可持久化线段树搞(总感觉不用 是我的错觉?)
然后就搞出来了……这TLE叫一个爽 上一个写法跑了整整30s我也是醉了 明明不强制在线还有40s的时限改成强制在线居然尼玛只剩15s了……
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 50500 using namespace std; struct abcd{ abcd *ls,*rs; int num; void* operator new (size_t size,abcd *_,abcd *__,int ___); }*tree[M],mempool[1001001],*C=mempool; int n,m,tot,block,ans; int a[M],l[M],r[M],belong[M]; int cnt[250][M]; pair<int,int>b[M]; int c[M],tim[M],T; void Update(int x) { for(;x;x-=x&-x) { if(tim[x]!=T) tim[x]=T,c[x]=0; c[x]++; } } int Get_Ans(int x) { int re=0; for(;x<=tot;x+=x&-x) if(tim[x]==T) re+=c[x]; return re; } void* abcd :: operator new (size_t size,abcd *_,abcd *__,int ___) { C->ls=_; C->rs=__; C->num=___; return C++; } abcd* Build_Tree(abcd *p,int x,int y,int val) { int mid=x+y>>1; if(x==y) return new (0x0,0x0,p->num+1)abcd; if(val<=mid) return new (Build_Tree(p->ls,x,mid,val),p->rs,p->num+1)abcd; else return new (p->ls,Build_Tree(p->rs,mid+1,y,val),p->num+1)abcd; } int Get_Ans(abcd *p1,abcd *p2,int x,int y,int l,int r) { int mid=x+y>>1; if(p1->num==p2->num) return 0; if(x==l&&y==r) return p2->num-p1->num; if(r<=mid) return Get_Ans(p1->ls,p2->ls,x,mid,l,r); if(l>mid) return Get_Ans(p1->rs,p2->rs,mid+1,y,l,r); return Get_Ans(p1->ls,p2->ls,x,mid,l,mid) + Get_Ans(p1->rs,p2->rs,mid+1,y,mid+1,r); } inline int Query(int x,int y) { int i,re=0; if(belong[x]==belong[y]) { ++T; for(i=x;i<=y;i++) re+=Get_Ans(a[i]+1),Update(a[i]); return re; } re+=cnt[belong[x]+1][y]; for(i=x;i<l[belong[x]+1];i++) re+=Get_Ans(tree[i],tree[y],0,tot+1,0,a[i]-1); return re; } int main() { //freopen("3744.in","r",stdin); //freopen("3744.out","w",stdout); int i,j,k,x,y; cin>>n; for(i=1;i<=n;i++) scanf("%d",&b[i].first),b[i].second=i; sort(b+1,b+n+1); for(i=1;i<=n;i++) { if(i==1||b[i].first!=b[i-1].first) ++tot; a[b[i].second]=tot; } tree[0]=new (0x0,0x0,0)abcd; tree[0]->ls=tree[0]->rs=tree[0]; for(i=1;i<=n;i++) tree[i]=Build_Tree(tree[i-1],0,tot+1,a[i]); block=static_cast<int>(sqrt(n)+1e-7); for(i=1;i<=n;i++) belong[i]=(i-1)/block+1; for(i=1;(i-1)*block+1<=n;i++) l[i]=(i-1)*block+1,r[i]=min(i*block,n); for(i=1;(i-1)*block+1<=n;i++) { ++T; for(j=(i-1)*block+1;j<=n;j++) { cnt[i][j]=cnt[i][j-1]+Get_Ans(a[j]+1); Update(a[j]); } } cin>>m; for(i=1;i<=m;i++) { scanf("%d%d",&x,&y);x^=ans;y^=ans; printf("%d\n", ans=Query(x,y) ); } }