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 }
    (╯▔皿▔)╯

     

posted @ 2019-08-10 19:26  连昵称都不能重复  阅读(167)  评论(0编辑  收藏  举报