zoukankan      html  css  js  c++  java
  • bzoj3295: [Cqoi2011]动态逆序对(cdq分治+树状数组)

    3295: [Cqoi2011]动态逆序对

    题目:传送门 


    题解:

       刚学完cdq分治,想起来之前有一道是树套树的题目可以用cdq分治来做...尝试一波

       还是太弱了...想到了要做两次cdq...然后伏地膜大佬

       其实需要维护的地方还是很容易想到的:

       第一维维护位置w,第二维维护数值s,第三维维护修改的时间t。

       那么对于t我们可以倒序插入,然后我们就可以把它看作t从小到大的插入结点(即使没有删除的点为了方便也要更新一下t)。

       再去观察就会发现,当我们插入一个节点t0时,我们需要求的就是在t0左边的比它大的数和在右边比它小的数:

       t<t0 w<w0 s>s0

       t<t0 w>w0 s<s0

       再转化一下符号:

       t<t0 w<w0 s<(n-s0+1)

       t<t0 w<(n-w0+1) s<s0

       这时候再看,不就是陌上花开吗!!!

       ps:大佬实在是太强了,记得开longlong(虽然不是很懂为什么,但是就是错了...)


    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 typedef long long LL;
     8 struct node
     9 {
    10     int w,s,t;//位置,数值,操作时间
    11     LL ans;//当前时间的答案 
    12 }a[110000],ba[110000];int n,m,b[110000];LL ans[110000];
    13 bool cmp(node n1,node n2){return n1.t<n2.t;}
    14 LL s[110000];
    15 int lowbit(int x){return x&-x;}
    16 void add(int x,int k){while(x<=n){s[x]+=k;x+=lowbit(x);}}
    17 int getsum(int x){LL ans=0;while(x){ans+=s[x];x-=lowbit(x);}return ans;}
    18 void cdq(int l,int r)
    19 {
    20     if(l==r)return ;
    21     int mid=(l+r)>>1;
    22     cdq(l,mid);cdq(mid+1,r);
    23     int i=l,j=mid+1,p=l;
    24     while(i<=mid && j<=r)
    25     {
    26         if(a[i].w<a[j].w)
    27         {
    28             add(a[i].s,1);
    29             ba[p++]=a[i++];
    30         }
    31         else
    32         {
    33             a[j].ans+=getsum(a[j].s);
    34             ba[p++]=a[j++];
    35         }
    36     }
    37     while(i<=mid)add(a[i].s,1),ba[p++]=a[i++];
    38     while(j<=r)a[j].ans+=getsum(a[j].s),ba[p++]=a[j++];
    39     
    40     for(int i=l;i<=mid;i++)add(a[i].s,-1);
    41     
    42     for(int i=l;i<=r;i++)a[i]=ba[i];
    43 }
    44 int main()
    45 {
    46     scanf("%d%d",&n,&m);int x,cc=n;
    47     for(int i=1;i<=n;i++)a[i].w=i,scanf("%d",&a[i].s);
    48     for(int i=1;i<=m;i++)scanf("%d",&x),b[x]=i;int s=m;
    49     for(int i=1;i<=n;i++)if(!b[i])b[i]=++s;
    50     for(int i=1;i<=n;i++)a[i].t=n-b[a[i].s]+1;
    51     sort(a+1,a+n+1,cmp);
    52     for(int i=1;i<=n;i++)a[i].s=n-a[i].s+1;
    53     cdq(1,n);
    54     sort(a+1,a+n+1,cmp);
    55     for(int i=1;i<=n;i++)
    56     {
    57         a[i].s=n-a[i].s+1;
    58         a[i].w=n-a[i].w+1;
    59     }
    60     cdq(1,n);
    61     for(int i=1;i<=n;i++)ans[a[i].t]=a[i].ans;
    62     for(int i=1;i<=n;i++)ans[i]+=ans[i-1];
    63     for(int i=n;i>=n-m+1;i--)printf("%lld
    ",ans[i]);
    64     return 0;
    65 }
  • 相关阅读:
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    DFS & BFS
    Binary Search
    博客保存
    python强大的正则表达式
    游戏注意的地方
    vim使用
    下一步的
    lua的动态特性
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8624136.html
Copyright © 2011-2022 走看看