Description
很久很以前,有一个古老的村庄——xiba村,村子里生活着n+1个村民,但由于历届村长恐怖而且黑暗的魔法统治下,村民们各自过着独立的生活,完全没有意识到其他n个人的存在。
但有一天,村民xiba臻无意中也得到了魔法,并发现了这个恐怖的事实。为了反抗村长,他走遍了全世界,找到了其他n个村民,并组织他们发动革命。但让这n个素不相识的村民(xiba臻已跟他们认识)同心协力去抵抗村长是很困难的,所以xiba臻决定先让他们互相认识。
这里,xiba臻用了xiba村特有的xiba思维:先让这n个人排成一列,并依次从1-n标号。然后每次xiba臻会选出一个区间[l, r],在这个区间中的人会去认识其他在这个区间中的人,但已经认识过得不会再去认识。这样,进行m次操作后,xiba臻认为这n个人能认识到许多人。
但是,为了精确地知道当前有多少对人已经认识了,xiba臻想要知道每次操作后会新产生出多少对认识的人,但这已是xiba思维无法解决的事了,你能帮帮他吗?
Input
第一行两个整数n,m。
接下来m行每行两个整数li,ri,表示每次操作的区间。
Output
共m行,每行一个整数ans_i,表示第i次操作后新产生出ans_i对认识的人。
Sample Input
5 5
2 3
2 4
3 5
1 5
2 4
Sample Output
1
2
2
5
0
Data Constraint
对于20%的数据,1≤n,m≤100。
对于50%的数据,1≤n,m≤5000。
对于100%的数据,1≤n,m≤300000,1≤li≤ri≤n。
Solution
可以看成每一个人对后面的连续的一段人是否有关系。
那么设f[ i ]表示i这个人和i+1到f[ i ]的人有关系。
则每次将L~R的区间的f[ i ]与R取max,最后所有f的变化值即为ans。
那么可以用吉司机线段树维护。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<ctime>
#define I int
#define ll long long
#define ls x<<1
#define rs ls|1
#define F(i,a,b) for(I i=a;i<=b;i++)
#define Fd(i,a,b) for(I i=a;i>=b;i--)
#define N 1000003
using namespace std;
I n,m,f[N],x,y,inf=0x7fffffff;
ll ans;
struct node{I mn,mn2,cmn,tmx;ll s;}t[N<<2];
void update(I x){
t[x].s=t[ls].s+t[rs].s;
if(t[ls].mn==t[rs].mn){
t[x].mn=t[ls].mn,t[x].cmn=t[ls].cmn+t[rs].cmn;
t[x].mn2=min(t[ls].mn2,t[rs].mn2);
}
else if(t[ls].mn<t[rs].mn){
t[x].mn=t[ls].mn,t[x].cmn=t[ls].cmn;
t[x].mn2=min(t[ls].mn2,t[rs].mn);
}
else{
t[x].mn=t[rs].mn,t[x].cmn=t[rs].cmn;
t[x].mn2=min(t[ls].mn,t[rs].mn2);
}
}
void push_max(I x,I v){
if(t[x].mn>=v) return;
t[x].s+=1LL*(v-t[x].mn)*t[x].cmn;
t[x].mn=t[x].tmx=v;
}
void down(I x){
if(t[x].tmx!=-inf){push_max(ls,t[x].tmx),push_max(rs,t[x].tmx);}
t[x].tmx=-inf;
}
void build(I x=1,I l=1,I r=n){
t[x].tmx=-inf;
if(l==r){
t[x].mn=t[x].s=l,t[x].cmn=1,t[x].mn2=inf;
return;
}
I M=l+r>>1;
build(ls,l,M),build(rs,M+1,r);
update(x);
}
void work(I l2,I r2,I v,I x=1,I l=1,I r=n){
if(r<l2||l>r2||t[x].mn>=v) return;
if(l>=l2&&r<=r2&&t[x].mn2>v){
if(t[x].mn<v) ans+=1LL*(v-t[x].mn)*t[x].cmn;
return push_max(x,v);
}
I M=l+r>>1;
down(x);
work(l2,r2,v,ls,l,M),work(l2,r2,v,rs,M+1,r);
update(x);
}
I main(){
freopen("ohmygod.in","r",stdin);
freopen("ohmygod.out","w",stdout);
scanf("%d%d",&n,&m);
build();
while(m--){
scanf("%d%d",&x,&y);
ans=0;
work(x,y,y);
printf("%lld\n",ans);
}
return 0;
}