题目大意
每次选择一次区间让区间内的人人两两认识(已经认识过的不会重复认识)
并在每次操作后输出增加了多少对认识的人。
抖机灵
我们设left[i]表示[left[i],i-1]的人都与i认识。
我们知道我们只需要求出每次操作后一共有多少对人认识,然后作差输出即可。
而且ans=∑ni=1i−left[i]
如果每次选择了[l,r],那么相当于让区间[l,r]的left值对l取min。
于是我们描述我们的任务:
1、支持区间取min。
2、支持求和。
segment tree beats?!!
单调性
然而这题存在特殊性。
注意到单调性:left[i-1]<=left[i]。
即i认识的i-1一定认识!
那么就好办了,每次操作找到区间[l,r]中最小的k满足left[k]>=l,然后相当于区间set。
至于如何找到这个k,我们只需区间保存最大值,然后利用线段树特性找就好了。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=300000+10;
int mx[maxn*5],set[maxn*5];
bool bz[maxn*5];
ll sum[maxn*5];
int i,j,k,l,r,t,n,m;
ll all,ans;
int read(){
int x=0;
char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x;
}
void mark(int p,int l,int r,int v){
mx[p]=v;
sum[p]=(ll)(r-l+1)*v;
bz[p]=1;
set[p]=v;
}
void down(int p,int l,int r){
int mid=(l+r)/2;
if (bz[p]){
mark(p*2,l,mid,set[p]);
mark(p*2+1,mid+1,r,set[p]);
set[p]=bz[p]=0;
}
}
void change(int p,int l,int r,int a,int b,int v){
if (l==a&&r==b){
mark(p,l,r,v);
return;
}
down(p,l,r);
int mid=(l+r)/2;
if (b<=mid) change(p*2,l,mid,a,b,v);
else if (a>mid) change(p*2+1,mid+1,r,a,b,v);
else change(p*2,l,mid,a,mid,v),change(p*2+1,mid+1,r,mid+1,b,v);
mx[p]=max(mx[p*2],mx[p*2+1]);
sum[p]=sum[p*2]+sum[p*2+1];
}
int find(int p,int l,int r,int a,int b,int v){
if (l==r){
if (mx[p]<v) return l+1;else return l;
}
down(p,l,r);
int mid=(l+r)/2;
if (l==a&&r==b){
if (mx[p]<v) return r+1;
if (mx[p*2]>=v) return find(p*2,l,mid,a,mid,v);
else return find(p*2+1,mid+1,r,mid+1,b,v);
}
if (b<=mid) return find(p*2,l,mid,a,b,v);
else if (a>mid) return find(p*2+1,mid+1,r,a,b,v);
else{
int t=find(p*2,l,mid,a,mid,v);
if (t<=mid) return t;else return find(p*2+1,mid+1,r,mid+1,b,v);
}
}
int main(){
freopen("ohmygod.in","r",stdin);freopen("ohmygod.out","w",stdout);
scanf("%d%d",&n,&m);
all=(ll)n*(n+1)/2;
fo(i,1,n) change(1,1,n,i,i,i);
fo(i,1,m){
scanf("%d%d",&j,&k);
t=find(1,1,n,j,k,j);
if (t<=k) change(1,1,n,t,k,j);
printf("%lld\n",all-sum[1]-ans);
ans=all-sum[1];
}
}