wa自动机 的 莫队 刷题记录
洛谷P2709小B的询问
- 莫队裸题,模板题
- 莫队就是把询问区间排个序,先按左端点的Pos排序(POS是分块那个数组),pos一样的按右端点排序
- 代码:
1 #include <bits/stdc++.h> 2 #define nmax 50010 3 4 using namespace std; 5 int a[nmax],ta[nmax],cnt[nmax]={0}; 6 int n,m,qn,k; 7 struct que{ 8 int l,r,p,id; 9 bool operator < (const que& x) const{ return (x.p==p)?(x.r>r):(x.p>p); } 10 }q[nmax]; 11 12 int main(){ 13 scanf("%d%d%d",&n,&qn,&k); 14 m=sqrt(n); 15 for (int i=1; i<=n; i++) scanf("%d",&a[i]); 16 for (int i=1; i<=qn; i++) { 17 scanf("%d%d",&q[i].l,&q[i].r); 18 q[i].p=(q[i].l-1)/m; 19 q[i].id=i; 20 } 21 sort(q+1,q+qn+1); 22 int l=q[1].l,r=q[1].l-1,ans=0; 23 for (int i=1; i<=qn; i++) { 24 while(l>q[i].l) l--,ans+=(2*cnt[a[l]]+1),cnt[a[l]]++; 25 while(r<q[i].r) r++,ans+=(2*cnt[a[r]]+1),cnt[a[r]]++; 26 while(l<q[i].l) ans-=(2*cnt[a[l]]-1),cnt[a[l]]--,l++; 27 while(r>q[i].r) ans-=(2*cnt[a[r]]-1),cnt[a[r]]--,r--; 28 ta[q[i].id]=ans; 29 } 30 for (int i=1; i<=qn; i++) printf("%d\n",ta[i]); 31 return 0; 32 }
BZOJ3289: Mato的文件管理
- 莫队加树状数组
- 每次区间长度增加的时候加上移动次数,减少的时候减去本来的移动次数(题意是只能移动相邻的嘛)
- 移动次数就是在当前区间的排名辣(因为要移动到那里去嘛,这个用树状数组很好维护。
- 没注意看题目,没有离散化re到死(果然人傻就是有各种各样的问题,嘤)
- 代码:
1 #include <bits/stdc++.h> 2 #define lowbit(x) x&(-x) 3 #define nmax 50005 4 5 using namespace std; 6 typedef long long ll; 7 int n,q,bn; //bn为每块的大小 8 int data[nmax],c[nmax]={0},lsh[nmax]; 9 ll ans[nmax]={0}; 10 struct seg{ 11 int l,r,pl,id; 12 bool operator < (const seg a) const{ return (a.pl==pl)?(a.r>r):(a.pl>pl); } 13 }qes[nmax]; 14 15 void upd(int x,int y){ //y决定是加是减 16 while(x<=n) { c[x]+=y; x+=lowbit(x); } 17 } 18 19 int myfind(int x){ 20 int ans=0; 21 while(x>0) { ans+=c[x]; x-=lowbit(x); } 22 return ans; 23 } 24 25 bool mycmp(int a,int b){ return data[a]<data[b]; } 26 27 int main(){ 28 cin>>n; 29 bn=sqrt(n); 30 for (int i=1; i<=n; i++) { scanf("%d",&data[i]); lsh[i]=i; } 31 sort(lsh+1,lsh+n+1,mycmp); 32 for (int i=1; i<=n; i++) data[ lsh[i] ]=i; 33 cin>>q; 34 for (int i=1; i<=q; i++) { 35 scanf("%d%d",&qes[i].l,&qes[i].r); 36 qes[i].id=i; 37 qes[i].pl=(qes[i].l-1)/bn+1; 38 } 39 sort(qes+1,qes+q+1); 40 int l=qes[1].l,r=qes[1].l-1,nowl=0,ta=0; //nowl现在该区间的长度 41 for (int i=1; i<=q; i++) { 42 while(qes[i].l<l) l--,upd(data[l],1),ta+=( myfind(data[l])-1 ),nowl++; 43 while(qes[i].r>r) nowl++,r++,upd(data[r],1),ta+=( nowl-myfind(data[r]) ); 44 while(qes[i].l>l) ta-=( myfind(data[l])-1 ),upd(data[l],-1),nowl--,l++; 45 while(qes[i].r<r) ta-=( nowl-myfind(data[r]) ),upd(data[r],-1),nowl--,r--; 46 ans[ qes[i].id ]=ta; 47 } 48 for (int i=1; i<=q; i++) printf("%lld\n",ans[i]); 49 return 0; 50 }