zoukankan      html  css  js  c++  java
  • bzoj 3262 陌上花开

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3262

    CDQ裸题。三维偏序。一眼看出一维排序、一维递归、一维树状数组。

    可是有相等的怎么办?

    然后看了TJ。https://blog.csdn.net/creationaugust/article/details/48788317

    https://blog.csdn.net/clove_unique/article/details/54235339

    其实分析一下:c的相等在树状数组里自己就能弄了;

      仅a相等:一开始排序的第二关键字是b,然后就没事了(递归中可以解决);

      仅b相等:毫无关系;

      a和b都相等:一开始排序的第二关键字是b的话,想一想发现只有最大的那个包含了所有,所以最后弄一弄就行了;

            或从一开始就找出所有a、b、c都相等的东西,记一个num。

    注意树状数组的边界是m!!!

    *先递归下去,再做本层的操作,本层的排序就不会对递归下去的东西造成影响。(当然也可以把本层的东西拿出来到别的数组里,对那个数组排序、操作)

      需要保证的是本层默认的:至少是mid左边的a一定小于mid右边的a。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5,M=2e5+5;
    int n,m,f[M],cnt[N],tot;
    struct Node{
        int a,b,c,sum,num;
    }t[N],s[N];
    bool cmpb(Node x,Node y){return x.b<y.b;}
    bool cmp(Node x,Node y){return x.a<y.a||(x.a==y.a&&x.b<y.b)||(x.a==y.a&&x.b==y.b&&x.c<y.c);}
    bool check(Node x,Node y){return x.a==y.a&&x.b==y.b&&x.c==y.c;}
    void add(int x,int v){for(;x<=m;x+=(x&-x))f[x]+=v;}  //x<=m!!!!!!!!!!!!
    int query(int x){int ret=0;for(;x;x-=(x&-x))ret+=f[x];return ret;}
    void cdq(int l,int r)
    {
        if(l==r)return;
        int mid=((l+r)>>1),p=l;
        cdq(l,mid);cdq(mid+1,r);
        sort(t+l,t+mid+1,cmpb);sort(t+mid+1,t+r+1,cmpb);    //sort左开右闭
        for(int i=mid+1;i<=r;i++)
        {
            while(p<=mid&&t[p].b<=t[i].b)add(t[p].c,t[p].num),p++;    //p<=mid!!!  //请不要把p++写在add里面 
            t[i].sum+=query(t[i].c);
        }
        for(int i=l;i<p;i++)add(t[i].c,-t[i].num);   //撤销
    //  sort(t+l,t+mid+1,cmpa);sort(t+mid+1,t+r+1,cmpa);    //撤销 
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d%d%d",&s[i].a,&s[i].b,&s[i].c);
        sort(s+1,s+n+1,cmp);int ct;
        for(int i=1;i<=n;i++)
        {
            ct=1;
            while(check(s[i],s[i+1]))ct++,i++;
            t[++tot]=s[i];t[tot].num=ct;
        }
        cdq(1,tot);
        for(int i=1;i<=tot;i++)cnt[t[i].sum+t[i].num-1]+=t[i].num;
        for(int i=0;i<n;i++)printf("%d
    ",cnt[i]);
        return 0;
    }
    
    View Code

    当然也可以先做完本层的,再排序回去。不过会很慢。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5,M=2e5+5;
    int n,m,f[M],cnt[N];
    struct Node{
        int a,b,c,sum,num;
    }t[N];
    bool cmpb(Node x,Node y){return x.b<y.b;}
    bool cmp(Node x,Node y){return x.a<y.a||(x.a==y.a&&x.b<y.b)||(x.a==y.a&&x.b==y.b&&x.c<y.c);}
    bool check(Node x,Node y){return x.a==y.a&&x.b==y.b&&x.c==y.c;}
    void add(int x,int v){for(;x<=m;x+=(x&-x))f[x]+=v;}  //x<=m!!!!!!!!!!!!
    int query(int x){int ret=0;for(;x;x-=(x&-x))ret+=f[x];return ret;}
    void cdq(int l,int r)
    {
        if(l==r)return;
        int mid=((l+r)>>1),p=l;
        sort(t+l,t+mid+1,cmpb);sort(t+mid+1,t+r+1,cmpb);    //sort左开右闭
        for(int i=mid+1;i<=r;i++)
        {
            while(p<=mid&&t[p].b<=t[i].b)add(t[p].c,1),p++;   //p<=mid!!!  //请不要把p++写在add里面 
            t[i].sum+=query(t[i].c);
        }
        for(int i=l;i<p;i++)add(t[i].c,-1);  //撤销
        sort(t+l,t+mid+1,cmp);sort(t+mid+1,t+r+1,cmp);  //撤销 
        cdq(l,mid);cdq(mid+1,r);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d%d%d",&t[i].a,&t[i].b,&t[i].c);
        sort(t+1,t+n+1,cmp);int ct;
        cdq(1,n);
        for(int i=1;i<=n;i++)
        {
            ct=1;
            while(check(t[i],t[i+1]))ct++,i++;
            cnt[t[i].sum]+=ct;
        }
        for(int i=0;i<n;i++)printf("%d
    ",cnt[i]);
        return 0;
    }
    View Code

    十分奇怪的是为什么不记num,然后弄先递归下去的版本,就WA了?

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5,M=2e5+5;
    int n,m,f[M],cnt[N];
    struct Node{
        int a,b,c,sum,num;
    }t[N];
    bool cmpb(Node x,Node y){return x.b<y.b;}
    bool cmp(Node x,Node y){return x.a<y.a||(x.a==y.a&&x.b<y.b)||(x.a==y.a&&x.b==y.b&&x.c<y.c);}
    bool check(Node x,Node y){return x.a==y.a&&x.b==y.b&&x.c==y.c;}
    void add(int x,int v){for(;x<=m;x+=(x&-x))f[x]+=v;}    //x<=m!!!!!!!!!!!!
    int query(int x){int ret=0;for(;x;x-=(x&-x))ret+=f[x];return ret;}
    void cdq(int l,int r)
    {
        if(l==r)return;
        int mid=((l+r)>>1),p=l;
        cdq(l,mid);cdq(mid+1,r);
        sort(t+l,t+mid+1,cmpb);sort(t+mid+1,t+r+1,cmpb);    //sort左开右闭
        for(int i=mid+1;i<=r;i++)
        {
            while(p<=mid&&t[p].b<=t[i].b)add(t[p].c,1),p++;    //p<=mid!!!    //请不要把p++写在add里面 
            t[i].sum+=query(t[i].c);
        }
        for(int i=l;i<p;i++)add(t[i].c,-1);    //撤销
    //    sort(t+l,t+mid+1,cmp);sort(t+mid+1,t+r+1,cmp);    //撤销 
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d%d%d",&t[i].a,&t[i].b,&t[i].c);
        sort(t+1,t+n+1,cmp);int ct;
        cdq(1,n);
        sort(t+1,t+n+1,cmp);//
        for(int i=1;i<=n;i++)
        {
            ct=1;
            while(check(t[i],t[i+1]))ct++,i++;
            cnt[t[i].sum]+=ct;
        }
        for(int i=0;i<n;i++)printf("%d
    ",cnt[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    ArrayAdapter
    给ListView设置emptyView
    ListView中item定位
    clipChildren和clipToPadding
    【热文】 为什么很多硅谷工程师偏爱 OS X,而不是 Linux 或 Windows?
    【热文】 为什么程序员痴迷于猫?
    欢迎使用 MWeb
    Android动画学习(二)——Tween Animation
    将博客搬至CSDN
    Android动画学习(一)——Android动画系统框架简介
  • 原文地址:https://www.cnblogs.com/Narh/p/9230515.html
Copyright © 2011-2022 走看看