CodeForces - 915E 動態開點線段樹||離散化線段樹
阿新 • • 發佈:2018-11-02
題意:
給定1-n的一段空區間,每次給出 x y z 的詢問,z == 1 時將 x - y 區間全部填充,否則為空,問最後一共有多少空區間
分析:
很明顯的線段樹題目,不過主要是想學習以下動態開點,不過陣列範圍自己一時間也還不懂怎麼處理。看cf上很多大佬STL做的,很是騷,%%%
#include<bits/stdc++.h> using namespace std; const int maxn=3e5+10; int ll[maxn*50],rr[maxn*50],sum[maxn*50],lazy[maxn*50]; int id; void push_down(int l,int r,int &rt){ if(lazy[rt]==-1) return; int mid=l+r>>1; if(l!=r){ //不是葉子節點則需要開闢左節點跟右節點。 if(ll[rt]==0) ll[rt]=++id; if(rr[rt]==0) rr[rt]=++id; lazy[ll[rt]]=lazy[rt]; lazy[rr[rt]]=lazy[rt]; sum[ll[rt]]=(mid-l+1)*lazy[rt]; sum[rr[rt]]=(r-mid)*lazy[rt]; } lazy[rt]=-1; } void change(int tl,int tr,int v,int l,int r,int &rt){ if(!rt) rt=++id; //動態開點就是什麼時候用什麼時候開點 if(r<tl||tr<l) return; if(tl<=l&&r<=tr){ lazy[rt]=v; sum[rt]=(r-l+1)*v; return; } push_down(l,r,rt); int mid=l+r>>1; change(tl,tr,v,l,mid,ll[rt]); change(tl,tr,v,mid+1,r,rr[rt]); sum[rt]=sum[ll[rt]]+sum[rr[rt]]; } int main(){ int l,r,x,y,z,rt,n,m; while(scanf("%d%d",&n,&m)!=EOF){ id=rt=0; memset(ll,0,sizeof ll); memset(rr,0,sizeof rr); memset(sum,0,sizeof sum); memset(lazy,-1,sizeof lazy); while(m--){ scanf("%d%d%d",&x,&y,&z); if(z==1) change(x,y,1,1,n,rt); else change(x,y,0,1,n,rt); printf("%d\n",n-sum[1]); } } return 0; }
#include<bits/stdc++.h> using namespace std; const int maxn=3e6+10; int x[maxn],y[maxn],f[maxn]; struct node{ int sum,lazy; }p[maxn<<2]; int id[maxn*6]; void build(int l,int r,int i){ p[i].sum=0;p[i].lazy=-1; if(l==r) return ; int mid=l+r>>1; build(l,mid,i<<1); build(mid+1,r,i<<1|1); } void update(int l,int r,int i){ if(p[i].lazy==-1) return ; int mid=l+r>>1; p[i<<1].sum=(id[mid]-id[l-1])*p[i].lazy; p[i<<1|1].sum=(id[r]-id[mid])*p[i].lazy; p[i<<1].lazy=p[i<<1|1].lazy=p[i].lazy; p[i].lazy=-1; } void change(int tl,int tr,int i,int l,int r,int v){ if(tl>r||tr<l) return ; if(tl<=l&&r<=tr){ p[i].sum=(id[r]-id[l-1])*v; p[i].lazy=v; return; } update(l,r,i); int mid=l+r>>1; change(tl,tr,i<<1,l,mid,v); change(tl,tr,i<<1|1,mid+1,r,v); p[i].sum=p[i<<1].sum+p[i<<1|1].sum; } int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ int cnt=0; id[++cnt]=1; id[++cnt]=n; for(int i=1;i<=m;i++){ scanf("%d%d%d",&x[i],&y[i],&f[i]); id[++cnt]=x[i]; id[++cnt]=y[i]; } sort(id+1,id+1+cnt); cnt=unique(id+1,id+1+cnt)-(id+1); int tot=cnt; for(int i=2;i<=cnt;i++){ if(id[i]-id[i-1]>1) id[++tot]=id[i-1]+1>n?n:id[i-1]+1; } sort(id+1,id+1+tot); cnt=unique(id+1,id+1+tot)-(id+1); tot=cnt; for(int i=cnt;i>1;i--){ if(id[i]-id[i-1]>1) id[++tot]=id[i]-1<1?1:id[i]-1; } sort(id+1,id+1+tot); cnt=unique(id+1,id+1+tot)-(id+1); build(1,cnt,1); for(int i=1;i<=m;i++){ int xx=lower_bound(id+1,id+1+cnt,x[i])-id; int yy=lower_bound(id+1,id+1+cnt,y[i])-id; if(f[i]==1){ change(xx,yy,1,1,cnt,1); }else change(xx,yy,1,1,cnt,0); printf("%d\n",n-p[1].sum); } } return 0; } /* 10 3 1 10 1 1 2 1 9 10 1 */