您的位置:首页 > 其它

线段树练习

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: