CF 283E Cow Tennis Tournament(线段树)

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

题意:给出n个人,每个人有个战力值,战力大的获胜。现在有k个区间,如果两个人的战力都在区间内,则会更改交战结果。问最后有多少个三元组(i,j,k)满足,i>j,j>k,k>i。
http://codeforces.com/contest/283/problem/E 
这题的一个转换是交补,C(n,3)是总共的三元组数目,求出有多少个不满足的。
不满足的肯定是其中1个人战胜了2个人。那么做法就是枚举这个人,判断他能战胜m个人,那么就应该减去C(m,2)
用线段树来维护。
初始状态全为0,更改则为1。
那么对于枚举当前人,他能战胜的,就是战力比他小的,而且没有更改状态的
以及战力比他大的但是更改状态了。也就是[1,i-1]中的0,以及[i+1,n]中的1数目。
维护two points更新区间即可。
即枚举当前人i,所有有效的更新区间是i所包含的区间,其余区间不要更新,或者更新两次抵消掉
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define lson (step<<1)
#define rson (step<<1|1)
#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define LL long long
using namespace std;
const int N=100005;
struct Seg_tree{
    int left,right;
    int cnt[2],cover;
}L[N<<2];
int n,k,s[N];
vector<pair<int,int> >change,other;
void push_up(int step){
    for(int i=0;i<2;i++)
        L[step].cnt[i]=L[lson].cnt[i]+L[rson].cnt[i];
}
void push_down(int step){
    if(L[step].cover){
        L[lson].cover^=1;
        L[rson].cover^=1;
        swap(L[lson].cnt[0],L[lson].cnt[1]);
        swap(L[rson].cnt[0],L[rson].cnt[1]);
        L[step].cover=0;
    }
}
void bulid(int step,int l,int r){
    L[step].left=l;
    L[step].right=r;
    L[step].cover=0;
    if(l==r){
        L[step].cnt[0]=1;
        L[step].cnt[1]=0;
        return ;
    }
    int m=(l+r)>>1;
    bulid(lson,l,m);
    bulid(rson,m+1,r);
    push_up(step);
}
void update(int step,int l,int r){
    if(L[step].left==l&&L[step].right==r){
        swap(L[step].cnt[0],L[step].cnt[1]);
        L[step].cover^=1;
        return ;
    }
    int m=(L[step].left+L[step].right)>>1;
    push_down(step);
    if(r<=m) update(lson,l,r);
    else if(l>m) update(rson,l,r);
    else{
        update(lson,l,m);
        update(rson,m+1,r);
    }
    push_up(step);
}
int query(int step,int l,int r,int c){
    if(L[step].left==l&&L[step].right==r)
        return L[step].cnt[c];
    int m=(L[step].left+L[step].right)>>1;
    push_down(step);
    if(r<=m) return query(lson,l,r,c);
    else if(l>m) return query(rson,l,r,c);
    else return query(lson,l,m,c)+query(rson,m+1,r,c);
}
int main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++)
        cin>>s[i];
    sort(s+1,s+1+n);
    bulid(1,1,n);
    for(int i=0;i<k;i++){
        int a,b;
        cin>>a>>b;
        a=lower_bound(s+1,s+1+n,a)-s;
        b=upper_bound(s+1,s+1+n,b)-s-1;
        if(a>b) continue;
        other.pb(mp(b,a));
        change.pb(mp(a,b));
    }
    sort(change.begin(),change.end());
    sort(other.begin(),other.end());
    LL ans=(LL)n*(n-1)*(n-2)/6;
    for(int i=1,j=0,r=0;i<=n;i++){
        while(j<change.size()&&change[j].first==i){
            update(1,change[j].first,change[j].second);
            j++;
        }
        int win=0;
        if(i>1) win+=query(1,1,i-1,0);
        if(i<n) win+=query(1,i+1,n,1);
        //cout<<win<<endl;
        ans-=(LL)win*(win-1)/2;
        while(r<other.size()&&other[r].first==i){
            update(1,other[r].second,other[r].first);
            r++;
        }
    }
    cout<<ans<<endl;
    return 0;
}


你可能感兴趣的:(CF 283E Cow Tennis Tournament(线段树))