线段树练习
2016-11-04 08:27
246 查看
背景
连着几天做计算几何,表示整个人都快要疯掉了。。昨天晚上看动漫+刷水题放松了一下题目
http://codevs.cn/problem/1082/http://codevs.cn/problem/4919/
http://codevs.cn/problem/4927/
题解
第一题,线段树模板上第二题,用w[i]表示这个节点所表示的区间里有多少除7余i的
第三题,各种乱搞,注意双标记的处理顺序,如果给一个有add标记的点加上set标记,则add标记要置零,对于有两个标记的先set再add。
代码
T1
//线段树练习3 #include <cstdio> #include <algorithm> #define maxn 200010 #define ll long long using namespace std; struct segtree { ll l, r, d, w; segtree *lch, *rch; }*root; ll N, a[maxn]; void pushdown(segtree *pos) { pos->w+=pos->d*(pos->r-pos->l+1); if(pos->lch)pos->lch->d+=pos->d; if(pos->rch)pos->rch->d+=pos->d; pos->d=0; } void add(segtree *pos, ll l, ll r, ll w) { pushdown(pos); ll mid=pos->l+pos->r>>1; if(l<=pos->l and r>=pos->r){pos->d+=w;return;} if(l<=mid)add(pos->lch,l,r,w),pos->w+=(min(mid,r)-max(l,pos->l)+1)*w; if(r>mid)add(pos->rch,l,r,w),pos->w+=(min(r,pos->r)-max(l,mid+1)+1)*w; } ll sum(segtree *pos, ll l, ll r) { pushdown(pos); ll mid=pos->l+pos->r>>1, ans=0; if(l<=pos->l and r>=pos->r)return pos->w; if(l<=mid){ans+=sum(pos->lch,l,r);} if(r>mid){ans+=sum(pos->rch,l,r);} return ans; } void build(segtree *pos, ll l, ll r) { ll mid=l+r>>1; pos->l=l,pos->r=r; if(l==r)pos->w=a[l]; else { build(pos->lch=new segtree,l,mid); build(pos->rch=new segtree,mid+1,r); pos->w=pos->lch->w+pos->rch->w; } } int main() { ll i, l, r, w, q, type; scanf("%lld",&N); for(i=1;i<=N;i++)scanf("%lld",a+i); build(root=new segtree,1,N); scanf("%lld",&q); for(i=1;i<=q;i++) { scanf("%lld%lld%lld",&type,&l,&r); if(type==2)printf("%lld\n",sum(root,l,r)); else{scanf("%lld",&w);add(root,l,r,w);} } return 0; }
T2
//线段树练习4 #include <cstdio> #include <algorithm> #define maxn 100010 using namespace std; struct node { int l, r, w[10], d; node *lch, *rch; }*root; int N, a[maxn]; void pushdown(node *pos) { int i, w[10]; for(i=0;i<7;i++)w[(i+pos->d)%7]=pos->w[i]; for(i=0;i<7;i++)pos->w[i]=w[i]; if(pos->l!=pos->r)pos->lch->d+=pos->d,pos->rch->d+=pos->d; pos->d=0; } void update(node *pos) //保证祖先到儿子信息正确才能调用 { int i; if(pos->l==pos->r)return; pushdown(pos->lch),pushdown(pos->rch); for(i=0;i<7;i++)pos->w[i]=pos->lch->w[i]+pos->rch->w[i]; } void add(node *pos, int l, int r, int w) { pushdown(pos); int i, mid=pos->l+pos->r>>1; if(l<=pos->l and r>=pos->r)pos->d+=w; else { if(l<=mid)add(pos->lch,l,r,w); if(r>mid)add(pos->rch,l,r,w); update(pos); } } int sum(node *pos, int l, int r) { pushdown(pos); int mid=pos->l+pos->r>>1, ans=0; if(l<=pos->l and r>=pos->r)return pos->w[0]; if(l<=mid)ans+=sum(pos->lch,l,r); if(r>mid)ans+=sum(pos->rch,l,r); return ans; } void build(node *pos, int l, int r) { int mid=l+r>>1; pos->l=l,pos->r=r; if(l==r){pos->w[a[l]%7]++;return;} build(pos->lch=new node,l,mid); build(pos->rch=new node,mid+1,r); update(pos); } int main() { int i, q, l, r, w, x; char s[100]; scanf("%d",&N); for(i=1;i<=N;i++)scanf("%d",a+i); build(root=new node,1,N); scanf("%d",&q); for(i=1;i<=q;i++) { scanf("%s%d%d",s,&l,&r); if(s[0]=='a') { scanf("%d",&w); add(root,l,r,w%7); } else printf("%d\n",sum(root,l,r)); } return 0; }
T3
//线段树练习5 #include <cstdio> #include <algorithm> #define maxn 100010 #define ll long long #define inf ((long long)1<<60) using namespace std; struct node { ll l, r, summ, minn, maxx, sett, add; node *lch, *rch; }*root; ll a[maxn], N; void pushdown(node *p) { if(p->sett!=-1) { p->minn=p->maxx=p->sett; p->summ=(p->r-p->l+1)*p->sett; if(p->lch) p->lch->sett=p->sett,p->rch->sett=p->sett,p->lch->add=0,p->rch->add=0; p->sett=-1; } if(p->add) { p->minn+=p->add,p->maxx+=p->add; p->summ+=(p->r-p->l+1)*p->add; if(p->lch)p->lch->add+=p->add,p->rch->add+=p->add; p->add=0; } } void update(node *p) { if(!p->lch)return; pushdown(p->lch),pushdown(p->rch); p->minn=min(p->lch->minn,p->rch->minn); p->maxx=max(p->lch->maxx,p->rch->maxx); p->summ=p->lch->summ+p->rch->summ; } void add(node *p, ll l, ll r, ll w) { pushdown(p); ll mid=p->l+p->r>>1; if(l<=p->l and r>=p->r)p->add+=w; else { if(l<=mid)add(p->lch,l,r,w); if(r>mid)add(p->rch,l,r,w); update(p); } } void sett(node *p, ll l, ll r, ll w) { pushdown(p); ll mid=p->l+p->r>>1; if(l<=p->l and r>=p->r)p->sett=w; else { if(l<=mid)sett(p->lch,l,r,w); if(r>mid)sett(p->rch,l,r,w); update(p); } } ll solve(node *p, ll l, ll r, ll type) { pushdown(p); ll mid=p->l+p->r>>1, ans1=-1, ans2=-1; if(l<=p->l and r>=p->r) { if(type==1)return p->summ; if(type==2)return p->maxx; if(type==3)return p->minn; } if(l<=mid)ans1=solve(p->lch,l,r,type); if(r>mid)ans2=solve(p->rch,l,r,type); if(type==1)return max(ans1,(ll)0)+max(ans2,(ll)0); if(type==2)return max(ans1,ans2); if(type==3)return min(ans1==-1?inf:ans1,ans2==-1?inf:ans2); } void build(node *p, ll l, ll r) { p->l=l,p->r=r;p->sett=-1; if(l==r){p->summ=p->maxx=p->minn=a[l];return;} ll mid=l+r>>1; build(p->lch=new node,l,mid); build(p->rch=new node,mid+1,r); update(p); } int main() { ll i, m, l, r, w; char type[100], c; scanf("%lld%lld",&N,&m); for(i=1;i<=N;i++)scanf("%lld",a+i); build(root=new node,1,N); for(i=1;i<=m;i++) { scanf("%s%lld%lld",type,&l,&r);c=type[1]; switch(c) { case 'u':printf("%lld\n",solve(root,l,r,1));break; case 'a':printf("%lld\n",solve(root,l,r,2));break; case 'i':printf("%lld\n",solve(root,l,r,3));break; case 'd':scanf("%lld",&w);add(root,l,r,w);break; case 'e':scanf("%lld",&w);sett(root,l,r,w); } } return 0; }
相关文章推荐
- 线段树练习2
- SSL 2647_线段树练习四_线段树
- poj 3264 小白算法练习 Balanced Lineup 线段树
- 【SSLGZ 2648】线段树练习五
- Codevs 4919 线段树练习4
- 线段树练习3
- 线段树 基础练习例子(一)
- [Codevs] 4919 线段树练习4
- hiho 22 线段树练习
- 形形色色的线段树练习——codevs线段树练习1-5:线段树,树状数组及分块模板
- 团体程序设计天梯赛-练习集 L3-002. 堆栈 线段树 单点更新 解题报告
- 【codevs 1080】线段树练习
- 团体程序设计天梯赛-练习集 -- L2-014. 列车调度(线段树)
- 【codevs1082】线段树练习3——树状数组(改段求段)
- 线段树练习(3)hdu2795 Billboard
- codevs 4919 线段树练习4
- codevs 1082 线段树练习3
- POJ A Simple Problem with Integers | 线段树基础练习
- 【codevs 1080】线段树练习 之 花样解法
- 【codevs 1081】线段树练习2(单点查询+区间修改)