转载请注明出处,谢谢http://blog.youkuaiyun.com/ACM_cxlove?viewmode=contents by---cxlove
题意:给出n个人,每个人有个战力值,战力大的获胜。现在有k个区间,如果两个人的战力都在区间内,则会更改交战结果。问最后有多少个三元组(i,j,k)满足,i>j,j>k,k>i。
这题的一个转换是交补,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;
}