码迷,mamicode.com
首页 > 其他好文 > 详细

283E&EZOJ #89 Cow Tennis Tournament

时间:2018-11-04 21:52:24      阅读:294      评论:0      收藏:0      [点我收藏+]

标签:统计   scan   sum   force   从后往前   name   奇数   algorithm   lld   

传送门

分析

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

不难想出所有情况为$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;
}

283E&EZOJ #89 Cow Tennis Tournament

标签:统计   scan   sum   force   从后往前   name   奇数   algorithm   lld   

原文地址:https://www.cnblogs.com/yzxverygood/p/9906005.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!