zoukankan      html  css  js  c++  java
  • 283E&EZOJ #89 Cow Tennis Tournament

    传送门

    分析

    我们考虑用所有的情况减去不合法的情况

    不难想出所有情况为$C_n^3$

    于是我们考虑不合法的情况

    我们知道对于一个不合法的三元组$(a,b,c)$一定是修改后$a<b,b>c$

    于是我们可以离散化后用线段树维护每个点被覆盖了几次

    所以每次对于一个点$i$,比它大的点的个数即为在它前面修改次数为偶数的数量加在它后面修改次数为奇数的数量

    而产生的不合法情况即为$C_{sum_i}^2$

    我们再统计前后两种情况的时候将修改排序然后分别从后往前和从前往后各跑一次即可

    每次只要区间不再覆盖点$i$则统计答案

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    struct node {
        long long le,ri;
    };
    node q[100100];
    long long d[400100],col[400100],n,m;
    long long a[100100],sum[100100];
    vector<long long>id;
    inline bool cmp1(const node x,const node y){
        return x.le==y.le?x.ri<y.ri:x.le<y.le;
    }
    inline bool cmp2(const node x,const node y){
        return x.ri==y.ri?x.le>y.le:x.ri>y.ri;
    }
    inline void update(long long le,long long ri,long long wh,long long x,long long y){
        if(x>y)return;
        if(le>=x&&ri<=y){
          col[wh]^=1;
          d[wh]=(ri-le+1)-d[wh];
          return;
        }
        long long mid=(le+ri)>>1;
        if(col[wh]){
          col[wh<<1]^=1;
          col[wh<<1|1]^=1;
          d[wh<<1]=(mid-le+1)-d[wh<<1];
          d[wh<<1|1]=(ri-mid)-d[wh<<1|1];
          col[wh]=0;
        }
        if(mid>=x)update(le,mid,wh<<1,x,y);
        if(mid<y)update(mid+1,ri,wh<<1|1,x,y);
        d[wh]=d[wh<<1]+d[wh<<1|1];
    }
    inline long long Q(long long le,long long ri,long long wh,long long x,long long y){
        if(x>y)return  0;
        if(le>=x&&ri<=y)return d[wh];
        long long mid=(le+ri)>>1,ans=0;
        if(col[wh]){
          col[wh<<1]^=1;
          col[wh<<1|1]^=1;
          d[wh<<1]=(mid-le+1)-d[wh<<1];
          d[wh<<1|1]=(ri-mid)-d[wh<<1|1];
          col[wh]=0;
        }
        if(mid>=x)ans+=Q(le,mid,wh<<1,x,y);
        if(mid<y)ans+=Q(mid+1,ri,wh<<1|1,x,y);
        d[wh]=d[wh<<1]+d[wh<<1|1];
        return ans;
    }
    int main(){
        long long i,j,k;
        scanf("%lld%lld",&n,&m);
        for(i=1;i<=n;i++)scanf("%lld",&a[i]),id.push_back(a[i]);;
        sort(id.begin(),id.end());
        id.erase(unique(id.begin(),id.end()),id.end());
        for(i=1;i<=m;i++)
          scanf("%lld%lld",&q[i].le,&q[i].ri);
        sort(q+1,q+m+1,cmp1);
        long long Ans=n*(n-1)*(n-2)/6;
        j=1;
        for(i=1;i<=m;i++){
          for(j;j<=lower_bound(id.begin(),id.end(),q[i].le)-id.begin();j++)
            sum[j]+=(n-j)-Q(1,n,1,j+1,n);
          update(1,n,1,lower_bound(id.begin(),id.end(),q[i].le)-id.begin()+1,
                 upper_bound(id.begin(),id.end(),q[i].ri)-id.begin());
        }
        for(j;j<=n;j++)sum[j]+=(n-j)-Q(1,n,1,j+1,n);
        memset(d,0,sizeof(d));
        memset(col,0,sizeof(col));
        sort(q+1,q+m+1,cmp2);
        j=n;
        for(i=1;i<=m;i++){
          for(j;j>=upper_bound(id.begin(),id.end(),q[i].ri)-id.begin()+1;j--)
            sum[j]+=Q(1,n,1,1,j-1);
          update(1,n,1,lower_bound(id.begin(),id.end(),q[i].le)-id.begin()+1,
                 upper_bound(id.begin(),id.end(),q[i].ri)-id.begin());
        }
        for(j;j>0;j--)sum[j]+=Q(1,n,1,1,j-1);
        for(i=1;i<=n;i++)Ans-=sum[i]*(sum[i]-1)/2;
        cout<<Ans;
        return 0;
    }
  • 相关阅读:
    Ubuntu12.04 安装网卡驱动
    C++类内存分布
    C++多态的实现及原理详细解析
    QT4.7.4在ubuntu10.10下的编译(转)
    FFMpeg处理RTMP流有两种方式
    C++中的单例模式
    C++ STL--stack/queue 的使用方法
    qt编译出现 /usr/bin/ld: cannot find -lQtCore的解决方法
    each()
    window.setTimeout() 和 window.setInterval() 使用说明
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9906005.html
Copyright © 2011-2022 走看看