线段树
ACM大牛的线段树总结。看完就懂了。(代码也是抄自那里。。
hdu1166 (基本线段树(然后表示不明白为什么输出优化WA了
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define qwq(x) for(edge *o=head[x];o;o=o->next) #define lson l,m,x<<1 #define rson m+1,r,x<<1|1 int read(){ int x=0;char c=getchar();bool f=true; while(!isdigit(c)) { if(c=='-') f=false;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return f?x:-x; } void print(int x){ char ch[10];int cur=0; if(x<0) putchar('-'),x=-x; while(x) ch[++cur]=x%10+'0',x/=10; for(int i=cur;i;i--) putchar(ch[i]); putchar('\n'); return ; } const int nmax=50005; const int inf=0x7f7f7f7f; int sum[nmax<<2]; void pushup(int x){ sum[x]=sum[x<<1]+sum[x<<1|1];return ; } int query(int l,int r,int x,int tl,int tr){ if(tl<=l&&tr>=r) return sum[x]; int m=(l+r)>>1;int tmp=0; if(tl<=m) tmp+=query(lson,tl,tr); if(tr>m) tmp+=query(rson,tl,tr); return tmp; } void build(int l,int r,int x){ if(l==r) { sum[x]=read();return ; } int m=(l+r)>>1; build(lson);build(rson);pushup(x); } void update(int l,int r,int x,int p,int add){ if(l==r) { sum[x]+=add;return ; } int m=(l+r)>>1; p<=m?update(lson,p,add):update(rson,p,add); pushup(x); } int main(){ int t=read(); rep(i,t){ printf("Case %d:\n",i); int n=read(); build(1,n,1); char c[10]; while(scanf("%s",c)){ if(c[0]=='E') break; int a=read(),b=read(); if(c[0]=='Q') printf("%d\n",query(1,n,1,a,b));//print(query(1,n,1,a,b)); else if(c[0]=='S') update(1,n,1,a,-b); else update(1,n,1,a,b); } } return 0; }
hdu1754 (裸
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define lson l,m,x<<1 #define rson m+1,r,x<<1|1 int read(){ int x=0;char c=getchar();bool f=true; while(!isdigit(c)){ if(c=='-') f=false;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return f?x:-x; } const int nmax=200005; const int inf=0x7f7f7f7f; int sum[nmax<<2]; void pushup(int x){ sum[x]=max(sum[x<<1],sum[x<<1|1]); } int qmax(int l,int r,int x,int tl,int tr){ if(tl<=l&&tr>=r) return sum[x]; int m=(l+r)>>1;int tmp=-inf; if(tl<=m) tmp=max(tmp,qmax(lson,tl,tr)); if(tr>m) tmp=max(tmp,qmax(rson,tl,tr)); return tmp; } void update(int l,int r,int x,int p,int add){ if(l==r) { sum[x]=add;return ; } int m=(l+r)>>1; p<=m?update(lson,p,add):update(rson,p,add); pushup(x); } void build(int l,int r,int x){ if(l==r) { sum[x]=read();return ; } int m=(l+r)>>1; build(lson);build(rson);pushup(x); } int main(){ int n,m; while(scanf("%d%d",&n,&m)==2){ build(1,n,1); rep(i,m){ char c=getchar();int a=read(),b=read(); if(c=='Q') printf("%d\n",qmax(1,n,1,a,b)); else update(1,n,1,a,b); } } return 0; }
hdu1698:区间修改(打标志。。。然后输出的时候.没有输出WA了。。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define lson l,m,x<<1 #define rson m+1,r,x<<1|1 int read(){ int x=0;char c=getchar();bool f=true; while(!isdigit(c)){ if(c=='-') f=false;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return f?x:-x; } const int nmax=100005; int sum[nmax<<2],col[nmax<<2]; void pushup(int x){ sum[x]=sum[x<<1]+sum[x<<1|1]; } void pushdown(int x,int cnt){ if(col[x]){ col[x<<1]=col[x<<1|1]=col[x]; sum[x<<1]=col[x]*(cnt-(cnt>>1)); sum[x<<1|1]=col[x]*(cnt>>1); col[x]=0; } } void build(int l,int r,int x){ if(l==r) { sum[x]=1;return ; } int m=(l+r)>>1; build(lson);build(rson);pushup(x); } void update(int tl,int tr,int p,int l,int r,int x){ if(tl<=l&&r<=tr) { sum[x]=p*(r-l+1);col[x]=p;return ; } pushdown(x,r-l+1); int m=(l+r)>>1; if(tl<=m) update(tl,tr,p,lson); if(tr>m) update(tl,tr,p,rson); pushup(x); } int main(){ int t=read(); rep(i,t){ int n=read(),m=read(); clr(col,0); build(1,n,1); rep(j,m){ int a=read(),b=read(),c=read();update(a,b,c,1,n,1); } printf("Case %d: The total value of the hook is %d.\n",i,sum[1]); } return 0; }
poj3468:同样是区间修改。(然后query的时候忘了pushdown了。手动模拟证实不是update写错。。然后一看query。。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define lson l,m,x<<1 #define rson m+1,r,x<<1|1 #define ll long long int read(){ int x=0;char c=getchar();bool f=true; while(!isdigit(c)){ if(c=='-') f=false;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return f?x:-x; } const int nmax=100005; ll sum[nmax<<2],col[nmax<<2]; void pushup(int x){ sum[x]=sum[x<<1]+sum[x<<1|1]; } void build(int l,int r,int x){ if(l==r){ sum[x]=read();return ; } int m=(l+r)>>1; build(lson);build(rson);pushup(x); } void pushdown(int x,int cnt){ if(col[x]){ ll tmp=col[x]; col[x<<1]+=tmp;col[x<<1|1]+=tmp; sum[x<<1]+=tmp*(cnt-(cnt>>1)); sum[x<<1|1]+=tmp*(cnt>>1); col[x]=0; } return ; } void update(int tl,int tr,int p,int l,int r,int x){ if(tl<=l&&tr>=r) { sum[x]+=(ll)(r-l+1)*p;col[x]+=p;return ; } pushdown(x,r-l+1); int m=(l+r)>>1; if(tl<=m) update(tl,tr,p,lson); if(tr>m) update(tl,tr,p,rson); pushup(x); } ll query(int tl,int tr,int l,int r,int x){ if(tl<=l&&r<=tr) return sum[x]; pushdown(x,r-l+1); int m=(l+r)>>1;ll ans=0; if(tl<=m) ans+=query(tl,tr,lson); if(tr>m) ans+=query(tl,tr,rson); return ans; } int main(){ int n=read(),m=read(); build(1,n,1);clr(col,0); // cout<<sum[1]; // printf("%lld\n",query(1,n,1,n,1)); // rep(i,4*n) printf("%d ",sum[i]); rep(i,m){ char ch=getchar(); if(ch=='Q') { int a=read(),b=read(); printf("%lld\n",query(a,b,1,n,1)); } else{ int a=read(),b=read(),c=read(); update(a,b,c,1,n,1); // rep(j,n*4) printf("%d:%d\n",j,sum[j]); } } return 0; }
hdu1394:(其实如果不是数据范围特殊的话根本不能用线段树做。。。逆序对。。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define lson l,m,x<<1 #define rson m+1,r,x<<1|1 int read(){ int x=0;char c=getchar();bool f=true; while(!isdigit(c)){ if(c=='-') f=false;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return f?x:-x; } const int nmax=5005; int sum[nmax<<2],x[nmax]; void pushup(int x){ sum[x]=sum[x<<1]+sum[x<<1|1]; } void build(int l,int r,int x){ if(l==r) return ; int m=(l+r)>>1; build(lson);build(rson);pushup(x); } int query(int tl,int tr,int l,int r,int x){ if(tl<=l&&tr>=r) return sum[x]; int m=(l+r)>>1;int ans=0; if(tl<=m) ans+=query(tl,tr,lson); if(tr>m) ans+=query(tl,tr,rson); return ans; } void update(int p,int tmp,int l,int r,int x){ if(l==r) { sum[x]=tmp;return ; } int m=(l+r)>>1; p<=m?update(p,tmp,lson):update(p,tmp,rson); pushup(x); return ; } int main(){ int n; while(scanf("%d",&n)==1){ build(1,n,1);clr(sum,0); int cnt=0; rep(i,n){ x[i]=read();x[i]++; if(x[i]!=n) cnt+=query(x[i]+1,n,1,n,1); update(x[i],1,1,n,1); } int ans=cnt; // cout<<cnt<<endl; rep(i,n){ cnt=cnt-2*x[i]+n+1; ans=min(ans,cnt); } printf("%d\n",ans); } return 0; }
poj2528:线段树+离散化。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define lson l,m,x<<1 #define rson m+1,r,x<<1|1 int read(){ int x=0;char c=getchar();bool f=true; while(!isdigit(c)){ if(c=='-') f=false;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return f?x:-x; } const int nmax=10005; int col[nmax<<4],v[nmax],x[nmax<<2],lx[nmax],rx[nmax]; int find(int l,int r,int a){ /*int m=(l+r)>>1; if(x[m]==a) return m; if(x[m]<a) return find(m+1,r,a); return find(l,m,a);*/ while(l<=r){ int m=(l+r)>>1; if(x[m]==a) return m; if(x[m]<a) l=m+1; else r=m-1; } return -1; } void pushdown(int x){ if(col[x]) col[x<<1]=col[x<<1|1]=col[x],col[x]=0; //注意if } void update(int tl,int tr,int p,int l,int r,int x){ if(tl<=l&&tr>=r) { col[x]=p;return ; } pushdown(x); int m=(l+r)>>1; if(tl<=m) update(tl,tr,p,lson); if(tr>m) update(tl,tr,p,rson); } void query(int l,int r,int x){ if(col[x]) { v[col[x]]=1; return ; } if(l==r) return ; int m=(l+r)>>1; query(lson);query(rson);return ; } int main(){ int t=read(); while(t--){ int n=read();x[0]=0; rep(i,n) x[++x[0]]=lx[i]=read(),x[++x[0]]=rx[i]=read(); sort(x+1,x+n+n+1); x[0]=0; rep(i,n+n) if(x[i]!=x[i-1]) x[++x[0]]=x[i]; // rep(i,x[0]) printf("%d ",x[i]); cout<<endl; int cur=x[0]; rep(i,x[0]-1) if(x[i+1]-x[i]>1) x[++cur]=x[i]+1; sort(x+1,x+cur+1); // rep(i,cur) printf("%d ",x[i]);cout<<endl; clr(col,0); rep(i,n){ int l=find(1,cur,lx[i]); int r=find(1,cur,rx[i]); update(l,r,i,1,cur,1); // printf("%d %d\n",l,r); } int ans=0;clr(v,0);query(1,cur,1); rep(i,n) if(v[i]) ans++; printf("%d\n",ans); } return 0; }
poj3667:求连续最长区间。维护lsum rsum msum即可。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define lson l,m,x<<1 #define rson m+1,r,x<<1|1 int read(){ int x=0;char c=getchar();bool f=true; while(!isdigit(c)) { if(c=='-') f=false;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return f?x:-x; } const int nmax=50005; const int inf=0x7f7f7f7f; int col[nmax<<2],lsum[nmax<<2],rsum[nmax<<2],msum[nmax<<2]; void pushup(int x,int cnt){ lsum[x]=(lsum[x<<1]==(cnt-(cnt>>1)))?lsum[x<<1]+lsum[x<<1|1]:lsum[x<<1]; rsum[x]=(rsum[x<<1|1]==(cnt>>1))?rsum[x<<1|1]+rsum[x<<1]:rsum[x<<1|1]; msum[x]=max(rsum[x<<1]+lsum[x<<1|1],max(msum[x<<1|1],msum[x<<1])); } void pushdown(int x,int cnt){ if(col[x]!=-1){ col[x<<1]=col[x<<1|1]=col[x]; lsum[x<<1]=rsum[x<<1]=msum[x<<1]=col[x]?0:cnt-(cnt>>1); lsum[x<<1|1]=rsum[x<<1|1]=msum[x<<1|1]=col[x]?0:(cnt>>1); col[x]=-1; } } void build(int l,int r,int x){ col[x]=-1,msum[x]=lsum[x]=rsum[x]=r-l+1; //col[x]!=0 if(l==r) return ; int m=(l+r)>>1;build(lson);build(rson); } void update(int tl,int tr,int p,int l,int r,int x){ if(tl<=l&&tr>=r){ if(p) col[x]=p,lsum[x]=rsum[x]=msum[x]=0; else col[x]=p,lsum[x]=rsum[x]=msum[x]=r-l+1; }else{ pushdown(x,r-l+1); int m=(l+r)>>1; if(tl<=m) update(tl,tr,p,lson); if(tr>m) update(tl,tr,p,rson); pushup(x,r-l+1); } } int query(int cnt,int l,int r,int x){ if(l==r) return l; pushdown(x,r-l+1); //look out int m=(l+r)>>1; if(msum[x<<1]>=cnt) return query(cnt,lson); if(rsum[x<<1]+lsum[x<<1|1]>=cnt) return m-rsum[x<<1]+1; return query(cnt,rson); } int main(){ int n=read(),m=read();build(1,n,1); // rep(i,n<<2) printf("%d:%d %d %d %d\n",i,lsum[i],rsum[i],msum[i],col[i]); rep(i,m){ int p=read(); if(p==1) { int tmp=read(); if(msum[1]<tmp) puts("0"); else { int cur=query(tmp,1,n,1);printf("%d\n",cur); update(cur,tmp+cur-1,1,1,n,1); } }else{ int a=read(),b=read();update(a,a+b-1,0,1,n,1); } } return 0; }
hdu2828:题目看起来挺水的。但是update的时候不知道怎么判断QAQ。。。就是不断的插入一些数,如果有了就放在他后面。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define lson l,m,x<<1 #define rson m+1,r,x<<1|1 int read(){ int x=0;char c=getchar();bool f=true; while(!isdigit(c)){ if(c=='-') f=false;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return f?x:-x; } const int nmax=200005; const int inf=0x7f7f7f7f; int sum[nmax<<2],t[nmax<<2],a[nmax],b[nmax]; void build(int l,int r,int x){ if(l==r) { sum[x]=1;return ; } int m=(l+r)>>1;build(lson);build(rson);sum[x]=sum[x<<1]+sum[x<<1|1]; } /*void update(int p,int add,int l,int r,int x){ if(l==r){ sum[x]=0;t[x]=add;return ; } int m=(l+r)>>1; if(p>m||p<=m&&!sum[x<<1]) update(m+1,add,rson); else update(p,add,lson);sum[x]=sum[x<<1]+sum[x<<1|1]; }*/ void update(int p,int add,int l,int r,int x){ if(l==r){ sum[x]=0;t[x]=add;return ; } int m=(l+r)>>1; sum[x<<1]>=p?update(p,add,lson):update(p-sum[x<<1],add,rson); sum[x]=sum[x<<1]+sum[x<<1|1]; } void query(int l,int r,int x){ if(l==r) { printf("%d ",t[x]);return ; } int m=(l+r)>>1;query(lson);query(rson);return ; } int main(){ int n; while(scanf("%d",&n)==1){ build(1,n,1); rep(i,n) a[i]=read(),b[i]=read(); for(int i=n;i;i--) update(a[i]+1,b[i],1,n,1)/*,printf("%d\n",sum[2])*/; query(1,n,1);printf("\n"); } return 0; }