zoukankan      html  css  js  c++  java
  • 莫队

     [2009国家集训队]小Z的袜子

    https://www.lydsy.com/JudgeOnline/problem.php?id=2038

     1 /****************************************************
     2     Time:704 ms
     3     Memory:3648 kb
     4 ****************************************************/
     5 
     6 const int N=50005;
     7 struct que
     8 {
     9     int l,r,z;
    10 }a[N],b[N];
    11 int col[N],c[N];
    12 ll fx[N],fy[N];
    13 int n,m,T,p,cc,t;
    14  
    15 bool cmp1(que x,que y){return x.l<y.l;}
    16 bool cmp2(que x,que y){return x.r<y.r;}
    17 ll gcd(ll x,ll y) { return y==0 ? x : gcd(y,x%y) ; }
    18  
    19 void calc(int s,int t,int dt)
    20 {
    21     FOR(i,s,t)
    22     {
    23         cc-=(ll)c[col[i]]*(c[col[i]]-1);
    24         c[col[i]]+=dt;
    25         cc+=(ll)c[col[i]]*(c[col[i]]-1);
    26     }
    27 }
    28  
    29 int main()
    30 {
    31     scanf("%d%d",&n,&m);
    32     FOR(i,1,n) scanf("%d",&col[i]);
    33     FOR(i,1,m) scanf("%d%d",&a[i].l,&a[i].r),a[i].z=i;
    34     sort(a+1,a+m+1,cmp1);
    35     //FOR(i,1,m) cerr<<a[i].l<<" "<<a[i].r<<" "<<a[i].z<<endl;
    36     T=sqrt(n*1.0);p=n/T+(n%T!=0);
    37     //cerr<<T<<" "<<p<<endl;
    38     for(rg int i=1,j=1;i<=p;++i)
    39     {
    40         for(t=0;j<=m && a[j].l>(i-1)*T && a[j].l<=i*T ; ++j) b[++t]=a[j];
    41         sort(b+1,b+t+1,cmp2);
    42         //cerr<<i<<" "<<j<<endl;
    43         //FOR(hhh,1,t) cerr << b[hhh].l << " "<< b[hhh].r << " "<< b[hhh].z << " "<<endl;
    44         int tl=b[1].l,tr=b[1].l-1;cc=0;
    45         memset(c,0,sizeof(c));
    46         FOR(k,1,t)
    47         {
    48             if(tl<b[k].l) calc(tl,b[k].l-1,-1);
    49             else if(tl>b[k].l) calc(b[k].l,tl-1,1);
    50             if(tr<b[k].r) calc(tr+1,b[k].r,1);
    51             else if(tr>b[k].r) calc(b[k].r+1,tr,-1);
    52             fx[b[k].z]=cc;fy[b[k].z]=b[k].r-b[k].l+1;
    53             tl=b[k].l,tr=b[k].r;
    54         }
    55     }
    56     FOR(i,1,m)
    57     {
    58         if((!fx[i])||(!fy[i])) {puts("0/1"); continue;}
    59         fy[i]=fy[i]*(fy[i]-1);
    60         cc=gcd(fx[i],fy[i]);
    61         printf("%lld/%lld
    ",fx[i]/cc,fy[i]/cc);
    62     }
    63     return 0;
    64 }

    带修改莫队

    普通莫队是不能带修改的

    我们可以强行让它可以修改,就像DP一样,可以强行加上一维时间维,表示这次操作的时间。

    即把询问 [l,r] 变成 [l,r,time]

    那么我们的坐标也可以在时间维上移动,即 [l,r,time] 多了一维可以移动的方向,可以变成:

    [l-1,r,time][l+1,r,time][l,r-1,time][l,r+1,time][l,r,time-1][l,r,time+1]

    这样的转移也是 O(1) 的,但是我们排序又多了一个关键字,再搞搞就行了

    可以用和普通莫队类似的方法排序转移,做到

    这一次我们排序的方式是以

    为一块,分成了

    块,第一关键字是左端点所在块,第二关键字是右端点所在块,第三关键字是时间。

    还是来证明一下时间复杂度(默认块大小为

    ):

    左右端点所在块不变,时间在排序后单调向右移,这样的复杂度是 O(n)若左右端点所在块改变,时间一次最多会移动n个格子,时间复杂度 O(n)左端点所在块一共有

    中,右端点也是

    种,一共

    种,每种乘上移动的复杂度 O(n) ,总复杂度

    树上莫队

    莫队只能处理线性问题,我们要把树强行压成一维的

    我们可以将树的括号序跑下来,把括号序分块,在括号序上跑莫队

    具体怎么做呢?

    dfs一棵树,然后如果dfs到x点,就push_back(x),dfs完x点,就直接push_back(-x),然后我们在挪动指针的时候

    新加入的值是x ---> add(x)新加入的值是-x ---> del(x)新删除的值是x ---> del(x)新删除的值是-x ---> add(x)

    这样的话,我们就把一棵树处理成了序列。

    好像还有对树的连通块分块的方法,不过好像比较难我也不会(

    例题是[WC2013]糖果公园,这题是带修改树上莫队

    题意是给你一棵树,每个点有颜色,每次询问

    val表示该颜色的价值

    cnt表示颜色出现的次数

    w表示该颜色出现i次后的价值

    先把树变成序列,然后每次添加/删除一个点,这个点的对答案的的贡献是可以在 O(1) 时间内获得的,即

    发现因为他会把起点的子树也扫了一遍,产生多余的贡献,怎么办呢?

    因为扫的过程中起点的子树里的点肯定会被扫两次,但贡献为0

    所以可以开一个vis数组,每次扫到点x,就把 vis_x 异或上1

    如果 vis_x=0 ,那这个点的贡献就可以不计

    所以可以用树上莫队来求

    修改的话,加上一维时间维即可,变成带修改树上莫队

    然后因为所包含的区间内可能没有LCA,对于没有的情况要将多余的贡献删除,然后就完事了

    参考资料

    https://baijiahao.baidu.com/s?id=1611364100257622493&wfr=spider&for=pc

  • 相关阅读:
    洛谷 P2695 骑士的工作
    洛谷 P2839 畅通工程
    hdu_5742_It's All In The Mind
    hdu_5734_Acperience
    hdu_5738_Eureka(脑洞)
    hdu_5724_Chess(组合博弈)
    Codeforces Round #363 (Div. 2)D. Fix a Tree(并查集)
    Codeforces Round #363 (Div. 2) B. One Bomb (水题)
    Codeforces Round #363 (Div. 2) C. Vacations(DP)
    hdu_5723_Abandoned country(最小生成树)
  • 原文地址:https://www.cnblogs.com/universeplayer/p/10558934.html
Copyright © 2011-2022 走看看