codeforces 493 div1 e
题解:
和这件zhcs的那题有点像
第一种做法是考虑i,i+1之间的贡献
这样子就是矩形加减然后求矩形最小值个数
另一种做法是我们从左向右维护mx-nx-r+l
跟之前那题一样我们知道这个的最小值为0
另外我们只需要从右向左维护一个单调队列,这样区间取min/max(每个数插入删除一次)
就可以变成分段区间+/-操作了
然后这样就变成区间+/-然后查询历史为0的个数
其实这等价于上一种+扫描线
之后这个地方非常套路。。刚开始并没有理解
首先每个点肯定要维护最小值以及最小值个数
我们对每个点再维护一个时间标记,表示这个点是0的时间
注意我们不能去记录这个时间节点是多少
因为这样标记无法合并,我们在区间修改了一个节点后,我们不能即时的对子区间进行修改
然后下一个标记打下来就出错了
我们去记录每个点为0的时间,并且在父亲方向上可以打增加时间的标记
如何在增加了标记之后下传呢
我们考虑这个点以上的标记影响的都是这整个区间
这个区间之前最小值为0的位置,现在也一定是最小值
所以我们判一下它和父亲最小值是否相同就可以了
代码:
#include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for (int i=h;i<=t;i++) #define dep(i,t,h) for (int i=t;i>=h;i--) #define me(x) memset(x,0,sizeof(x)) #define ll long long #define mep(x,y) memcpy(x,y,sizeof(y)) #define mid ((h+t)>>1) namespace IO{ char ss[1<<24],*A=ss,*B=ss; IL char gc() { return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++; } template<class T>void read(T &x) { rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48); while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; } char sr[1<<24],z[20]; int Z,C=-1; template<class T>void wer(T x) { if (x<0) sr[++C]='-',x=-x; while (z[++Z]=x%10+48,x/=10); while (sr[++C]=z[Z],--Z); } IL void wer1() { sr[++C]=' ';} IL void wer2() { sr[++C]='\n';} template<class T>IL void maxa(T &x,T y) { if (x<y) x=y;} template<class T>IL void mina(T &x,T y) { if (x>y) x=y;} template<class T>IL T MAX(T x,T y) {return x>y?x:y;} template<class T>IL T MIN(T x,T y) {return x<y?x:y;} }; using namespace IO; const int N=1.5e5; int v[N],q,n,pos[N],cnt,p[N]; struct re{ int a,b,c,d; }a[N*4],b[N*10]; ll ans[N*4]; void change(int x1,int x2,int y1,int y2,int k) { b[++cnt]=(re){x1,y1,y2,k}; b[++cnt]=(re){x2+1,y1,y2,-k}; } const int N1=N*4; struct sgt{ ll now[N1]; int tim[N1],num[N1],v[N1],lazy[N1]; void build(int x,int h,int t) { num[x]=(t-h+1); if (h==t) return; build(x*2,h,mid); build(x*2+1,mid+1,t); } IL void down(int x) { if (lazy[x]) { lazy[x*2]+=lazy[x]; lazy[x*2+1]+=lazy[x]; v[x*2]+=lazy[x]; v[x*2+1]+=lazy[x]; lazy[x]=0; } if (tim[x]) { if (v[x*2]==v[x]) { now[x*2]+=1ll*tim[x]*num[x*2]; tim[x*2]+=tim[x]; } if (v[x*2+1]==v[x]) { now[x*2+1]+=1ll*tim[x]*num[x*2+1]; tim[x*2+1]+=tim[x]; } tim[x]=0; } } IL void updata(int x) { now[x]=now[x*2]+now[x*2+1]; v[x]=MIN(v[x*2],v[x*2+1]); num[x]=0; if (v[x]==v[x*2]) num[x]+=num[x*2]; if (v[x]==v[x*2+1]) num[x]+=num[x*2+1]; } void change(int x,int h,int t,int h1,int t1,int k) { if (h1<=h&&t<=t1) { v[x]+=k; lazy[x]+=k; return; } down(x); if (h1<=mid) change(x*2,h,mid,h1,t1,k); if (mid<t1) change(x*2+1,mid+1,t,h1,t1,k); updata(x); } ll query(int x,int h,int t,int h1,int t1) { if (h1<=h&&t<=t1) return(now[x]); down(x); ll ans=0; if (h1<=mid) ans+=query(x*2,h,mid,h1,t1); if (mid<t1) ans+=query(x*2+1,mid+1,t,h1,t1); return ans; } }S; bool cmp(re x,re y) { return x.a<y.a; } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); read(n); rep(i,1,n) read(v[i]),pos[v[i]]=i; rep(i,1,n-1) { change(1,i,i+1,n,1); change(i+1,n,1,i,1); int x1=pos[i],x2=pos[i+1]; if (x1>x2) swap(x1,x2); change(1,x1,x2,n,-1); change(x2,n,1,x1,-1); } read(q); int q1=q*4; rep(i,1,q) { int x,y; read(x); read(y); a[i*4-3]=(re){y,y,i*4-3}; a[i*4-2]=(re){x-1,y,i*4-2}; a[i*4-1]=(re){y,x-1,i*4-1}; a[i*4]=(re){x-1,x-1,i*4}; p[i]=y-x+1; } int now=1,lst=1; S.build(1,1,n); sort(a+1,a+q1+1,cmp); sort(b+1,b+cnt+1,cmp); rep(i,1,q1) { while(now<=cnt&&b[now].a<=a[i].a) { S.tim[1]+=b[now].a-lst; S.now[1]+=1ll*(b[now].a-lst)*S.num[1]; lst=b[now].a; S.change(1,1,n,b[now].b,b[now].c,b[now].d); now++; } S.tim[1]+=a[i].a+1-lst; S.now[1]+=1ll*(a[i].a+1-lst)*S.num[1]; lst=a[i].a+1; if (a[i].b) ans[a[i].c]=S.query(1,1,n,1,a[i].b); } rep(i,1,q) wer((ans[i*4-3]-ans[i*4-2]-ans[i*4-1]+ans[i*4]-p[i])/2+p[i]),wer2(); fwrite(sr,1,C+1,stdout); return 0; }