题解:CF283E Cow Tennis Tournament
首先我们先离散化掉所有值。
接下来我们考虑容斥掉答案,改为统计不满足条件的三元环。
我们考虑一下如何统计不满足条件的三元环,发现一个这样的三元环中,一定有且仅有一个点指向另外两个点,也就是说对于每一个点,这个点和他指向的任意两个点都构成这样的三元环。也就是说设点
接下来考虑如何统计
我们考虑枚举当前点
为了方便维护,
维护
下附代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<unordered_map>
#include<queue>
#define int long long
#define PII pair<int,int>
using namespace std;
int n,k,s[100005],q[100005],tot;
priority_queue<PII,vector<PII>,greater<PII>>q1,q2;
struct node{
int cnt,lz;
}tr[400005];
unordered_map<int,int>mp;
void pushdown(int k,int l,int r,int mid){
if(tr[k].lz){
tr[k*2].cnt=mid-l+1-tr[k*2].cnt;tr[k*2].lz^=1;
tr[k*2+1].cnt=r-mid-tr[k*2+1].cnt;tr[k*2+1].lz^=1;
tr[k].lz=0;
}
}
void pushup(int k){
tr[k].cnt=tr[k*2].cnt+tr[k*2+1].cnt;
}
void change(int k,int l,int r,int x,int y){
if(r<x||l>y) return;
if(x<=l&&r<=y){
tr[k].lz^=1;tr[k].cnt=r-l+1-tr[k].cnt;
return;
}
int mid=(l+r)/2;
pushdown(k,l,r,mid);
change(k*2,l,mid,x,y);change(k*2+1,mid+1,r,x,y);
pushup(k);
}
int query(int k,int l,int r,int x,int y){
if(r<x||l>y) return 0;
if(x<=l&&r<=y) return tr[k].cnt;
int mid=(l+r)/2;
pushdown(k,l,r,mid);
return query(k*2,l,mid,x,y)+query(k*2+1,mid+1,r,x,y);
}
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>s[i],q[i]=s[i];
sort(q+1,q+n+1);
for(int i=1;i<=n;i++){
if(q[i]!=q[i-1]) mp[q[i]]=++tot;
}
for(int i=1;i<=k;i++){
int l,r;cin>>l>>r;
l=mp[q[lower_bound(q+1,q+n+1,l)-q]];
r=mp[q[upper_bound(q+1,q+n+1,r)-q-1]];
if(!l||!r||l==r) continue;
q1.push({r,l});q2.push({l,r});
}
int ans=n*(n-1)*(n-2)/6;
for(int i=1;i<=n;i++){
while(q1.size()&&q1.top().first<i) change(1,1,n,q1.top().second,q1.top().first),q1.pop();
while(q2.size()&&q2.top().first<=i) change(1,1,n,q2.top().first,q2.top().second),q2.pop();
int cnt=(i>1?i-1-query(1,1,n,1,i-1):0)+(i<n?query(1,1,n,i+1,n):0);
ans-=cnt*(cnt-1)/2;
}
cout<<ans<<endl;
return 0;
}