您的位置:首页 > 其它

[kuangbin带你飞]专题七 线段树

2015-10-01 15:05 429 查看
点击打开链接

A(hdu 1166 敌兵布阵 )中文体面,线段树单点更新,求一段区间和

#include<stdio.h>
#include<string.h>
#include<stack>
#include<string>
#include<math.h>
#include<queue>
#include<set>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
using namespace std;
#define LL long long
#define inf 1<<31
#define N 50010
#define mod 1000000007
struct node
{
int l,r,sum;
}tree[N<<2];
void pushup(int rt)
{
tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
}
void build(int l,int r,int rt)
{
tree[rt].l=l;
tree[rt].r=r;
tree[rt].sum=0;
if(l==r)
{
scanf("%d",&tree[rt].sum);
return ;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
pushup(rt);
}
void updata(int x,int y,int rt)
{
if(tree[rt].l==tree[rt].r)
{
tree[rt].sum+=y;
return ;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
if(x<=mid) updata(x,y,rt<<1);
else updata(x,y,rt<<1|1);
pushup(rt);
}
int query(int x,int y,int rt)
{
if(tree[rt].l==x&&tree[rt].r==y)
{
return tree[rt].sum;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
if(y<=mid) return query(x,y,rt<<1);
else if(x>mid) return query(x,y,rt<<1|1);
else
return query(x,mid,rt<<1)+query(mid+1,y,rt<<1|1);
}
int main()
{
int i,j,n,m,t,x,y,ca=0;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
build(1,n,1);
char s[10];
printf("Case %d:\n",++ca);
while(scanf("%s",s),s[0]!='E')
{
scanf("%d%d",&x,&y);
if(s[0]=='Q')
printf("%d\n",query(x,y,1));
else if(s[0]=='A')
updata(x,y,1);
else if(s[0]=='S')
updata(x,-y,1);;
}
}
return 0;
}
B(hdu 1754 I Hate It)中文体面,线段树单点更新,求区间最大值

#include<stdio.h>
#include<string.h>
#include<stack>
#include<string>
#include<math.h>
#include<queue>
#include<set>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
using namespace std;
#define LL long long
#define inf 1<<31
#define N 200010
struct node
{
int l,r,Max;
}tree[N<<2];
void build(int l,int r,int rt)
{
tree[rt].l=l;
tree[rt].r=r;
if(l==r)
{
scanf("%d",&tree[rt].Max);
return ;
}
int mid=(r+l)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
tree[rt].Max=max(tree[rt<<1].Max,tree[rt<<1|1].Max);
}
int ans;
void query(int l,int r,int rt)
{
if(tree[rt].l==l&&tree[rt].r==r)
{
ans=max(ans,tree[rt].Max);
return ;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
if(l>mid) query(l,r,rt<<1|1);
else if(r<=mid) query(l,r,rt<<1);
else
{
query(l,mid,rt<<1);
query(mid+1,r,rt<<1|1);
}
}
void updata(int x,int y,int rt)
{
if(tree[rt].l==tree[rt].r)
{
tree[rt].Max=y;
return ;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
if(x>mid) updata(x,y,rt<<1|1);
else updata(x,y,rt<<1);
tree[rt].Max=max(tree[rt<<1].Max,tree[rt<<1|1].Max);
}
int main()
{
int i,j,n,m,x,y;
char s[3];
while(scanf("%d%d",&n,&m)!=-1)
{
build(1,n,1);
for(i=1;i<=m;i++)
{
scanf("%s%d%d",s,&x,&y);
if(s[0]=='Q')
{
ans=-1;
query(x,y,1);
printf("%d\n",ans);
}
else updata(x,y,1);
}
}
return 0;
}
C(poj 3468 A Simple Problem with Integers)线段树的区间更新区间求和

#include<stdio.h>
#include<string.h>
#include<stack>
#include<string>
#include<math.h>
#include<queue>
#include<set>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
using namespace std;
#define LL long long
#define inf 1<<31
#define N 100010
struct node
{
int l,r;
LL sum,add;//加的数不直接更新到叶子节点,而是先存到add中
}tree[N<<2];
void pushup(int rt)
{
tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
}
void build(int l,int r,int rt)
{
tree[rt].l=l;tree[rt].r=r;
tree[rt].sum=tree[rt].add=0;
if(l==r)
{
scanf("%lld",&tree[rt].sum);
return ;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
pushup(rt);
}
void pushdown(int rt)
{
int len=tree[rt].r-tree[rt].l+1;
tree[rt<<1].add+=tree[rt].add;
tree[rt<<1|1].add+=tree[rt].add;

tree[rt<<1].sum+=tree[rt].add*(len-len/2);
tree[rt<<1|1].sum+=tree[rt].add*(len/2);
tree[rt].add=0;
}
LL query(int x,int y,int rt)
{
if(tree[rt].l==x&&tree[rt].r==y)
return tree[rt].sum;
int mid=(tree[rt].l+tree[rt].r)>>1;
pushdown(rt);
if(y<=mid) return query(x,y,rt<<1);
else if(x>mid) return query(x,y,rt<<1|1);
else return query(x,mid,rt<<1)+query(mid+1,y,rt<<1|1);
}
void updata(int x,int y,LL z,int rt)
{
if(tree[rt].l==x&&tree[rt].r==y)
{
tree[rt].add+=z;
tree[rt].sum+=(y-x+1)*z;
return ;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
pushdown(rt);
if(y<=mid) updata(x,y,z,rt<<1);
else if(x>mid) updata(x,y,z,rt<<1|1);
else {
updata(x,mid,z,rt<<1);
updata(mid+1,y,z,rt<<1|1);
}
pushup(rt);
}
int main()
{
int i,j,n,m;
char s[3];
int x,y;
LL z;
while(scanf("%d%d",&n,&m)!=-1)
{
build(1,n,1);
while(m--)
{
scanf("%s",s);
if(s[0]=='Q')
{
scanf("%d%d",&x,&y);
printf("%lld\n",query(x,y,1));
}
else
{
scanf("%d%d%lld",&x,&y,&z);
updata(x,y,z,1);
}
}
}
return 0;
}
D(poj 2528 Mayor's posters )线段树+离散化,就是在墙上贴海报,当前贴的海报可以把以前的海报覆盖掉,问最后还能看见多少海报

#include<stdio.h>
#include<string.h>
#include<stack>
#include<string>
#include<math.h>
#include<queue>
#include<set>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
using namespace std;
#define LL long long
#define inf 1<<31
#define N 20010
struct node
{
int l,r,c;
}tree[N<<2];
struct Line
{
int l,r;
}a
;
int key
,tot,ans;
bool mark
;
void build(int l,int r,int rt)
{
tree[rt].l=l;tree[rt].r=r;
tree[rt].c=0;
if(l==r) return ;
int mid=(tree[rt].l+tree[rt].r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
}
int find_p(int x)
{
int low=1,high=tot;
while(low<=high)
{
int mid=(low+high)>>1;
if(key[mid]==x) return mid;
else if(x<key[mid])
high=mid-1;
else low=mid+1;
}
}
void updata(int l,int r,int c,int rt)
{
if(tree[rt].l==l&&tree[rt].r==r)
{
tree[rt].c=c;
return ;
}
if(tree[rt].c)
{
tree[rt<<1].c=tree[rt<<1|1].c=tree[rt].c;
tree[rt].c=0;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
if(r<=mid) updata(l,r,c,rt<<1);
else if(l>mid) updata(l,r,c,rt<<1|1);
else
{
updata(l,mid,c,rt<<1);
updata(mid+1,r,c,rt<<1|1);
}
}
void query(int rt)
{
if(tree[rt].c)
{
if(mark[tree[rt].c]==0)
{
mark[tree[rt].c]=1;
ans++;
}
return ;
}
query(rt<<1);
query(rt<<1|1);
}
int main()
{
int i,j,n,m,t;
scanf("%d",&t);
while(t--)
{
memset(mark,0,sizeof(mark));
scanf("%d",&n);
tot=0;
for(i=1;i<=n;i++)
{
scanf("%d%d",&a[i].l,&a[i].r);
key[++tot]=a[i].l;key[++tot]=a[i].r;
}
sort(key+1,key+1+tot);
tot=unique(key+1,key+1+tot)-(key+1);//数组去重
//        printf("%d\n",tot);
build(1,tot,1);
for(i=1;i<=n;i++)//离散化
{
int L=find_p(a[i].l);
int R=find_p(a[i].r);
updata(L,R,i,1);
}
ans=0;
query(1);
printf("%d\n",ans);
}
return 0;
}
E(hdu 1698 just a hook) 还是区间操作,代码点击打开链接

F(zoj 1610 Count the Colors)

#include<stdio.h>
#include<string.h>
#include<stack>
#include<string>
#include<math.h>
#include<queue>
#include<set>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
using namespace std;
#define LL long long
#define inf 1<<31
#define N 8010
struct node
{
int l,r,c;
}tree[N<<2];
int col
,ans
;//col[i]是i位置颜色的种类,ans[i]是颜色i的段数
void build(int l,int r,int rt)
{
tree[rt].l=l;
tree[rt].r=r;
tree[rt].c=-1;
if(r-l==1) return ;//涂色是一小段区间
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid,r,rt<<1|1);
}
void updata(int l,int r,int c,int rt)
{
if(tree[rt].l==l&&tree[rt].r==r)
{
tree[rt].c=c;
return ;
}
if(tree[rt].r-tree[rt].l==1) return ;

int mid=(tree[rt].l+tree[rt].r)>>1;
if(tree[rt].c!=-1)
{
tree[rt<<1].c=tree[rt<<1|1].c=tree[rt].c;
tree[rt].c=-1;
}
if(r<=mid) updata(l,r,c,rt<<1);
else if(l>=mid) updata(l,r,c,rt<<1|1);
else
{
updata(l,mid,c,rt<<1);
updata(mid,r,c,rt<<1|1);
}
}
void query(int rt)
{
if(tree[rt].c!=-1)
{
for(int i=tree[rt].l;i<tree[rt].r;i++)
col[i]=tree[rt].c;
return ;
}
if(tree[rt].r-tree[rt].l==1) return ;

query(rt<<1);
query(rt<<1|1);
}
int main()
{
int i,j,n,m;
while(scanf("%d",&n)!=EOF)
{
int x,y,z;
build(0,8000,1);
for(i=0;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
updata(x,y,z,1);
}
memset(ans,0,sizeof(ans));
memset(col,-1,sizeof(col));
query(1);
for(i=0;i<=8000;i++)
{
if(col[i]==-1) continue;
if(col[i]!=col[i+1])
ans[col[i]]++;
}
for(i=0;i<=8000;i++)
{
if(ans[i]==0) continue;
printf("%d %d\n",i,ans[i]);
}
puts("");
}
return 0;
}

G 简单的单点更新

#include<stdio.h>
#include<string.h>
#include<stack>
#include<string>
#include<math.h>
#include<queue>
#include<set>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
using namespace std;
#define LL long long
#define inf 1<<30
#define N 50010
struct node
{
int l,r,Min,Max;
}tree[N<<2];
int resmin,resmax;
void build(int l,int r,int rt)
{
tree[rt].l=l;
tree[rt].r=r;
if(l==r)
{
scanf("%d",&tree[rt].Min);
tree[rt].Max=tree[rt].Min;
return ;
}
int mid=(r+l)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
tree[rt].Min=min(tree[rt<<1].Min,tree[rt<<1|1].Min);
tree[rt].Max=max(tree[rt<<1].Max,tree[rt<<1|1].Max);
}
void query(int l,int r,int rt)
{
if(tree[rt].l==l&&tree[rt].r==r)
{
resmin=min(resmin,tree[rt].Min);
resmax=max(resmax,tree[rt].Max);
return ;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
if(l>mid) query(l,r,rt<<1|1);
else if(r<=mid) query(l,r,rt<<1);
else
{
query(l,mid,rt<<1);
query(mid+1,r,rt<<1|1);
}
}
int main()
{
int m,n,j,i,a,b;
while(scanf("%d%d",&n,&m)!=-1)
{
build(1,n,1);
for(i=0;i<m;i++)
{
resmin=inf;resmax=-inf;
scanf("%d%d",&a,&b);
query(a,b,1);
printf("%d\n",resmax-resmin);
}
}
return 0;
}
I(hdu 1540 Tunnel Warfare)单点更新,区间合并、查询

#include<stdio.h>
#include<string.h>
#include<stack>
#include<string>
#include<math.h>
#include<queue>
#include<set>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
using namespace std;
#define LL long long
#define inf 1<<30
#define N 50010
struct node
{
int l,r,lans,rans,ans;
}tree[N<<2];
void pushup(int rt)
{
if(tree[rt<<1].ans==tree[rt<<1].r-tree[rt<<1].l+1)
tree[rt].lans=tree[rt<<1].ans+tree[rt<<1|1].lans;
else tree[rt].lans=tree[rt<<1].lans;

if(tree[rt<<1|1].ans==tree[rt<<1|1].r-tree[rt<<1|1].l+1)
tree[rt].rans=tree[rt<<1|1].ans+tree[rt<<1].rans;
else tree[rt].rans=tree[rt<<1|1].rans;

tree[rt].ans= max(max(tree[rt<<1].ans,tree[rt<<1|1].ans),tree[rt<<1].rans+tree[rt<<1|1].lans);
}
void build(int l,int r,int rt)
{
tree[rt].l=l;tree[rt].r=r;
tree[rt].lans=tree[rt].rans=tree[rt].ans=r-l+1;
if(l==r)
return ;
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
}
void updata(int x,int rt,int c)
{
if(tree[rt].l==tree[rt].r)
{
tree[rt].ans=tree[rt].lans=tree[rt].rans=c;
return ;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
if(x<=mid) updata(x,rt<<1,c);
else updata(x,rt<<1|1,c);
pushup(rt);
}
int query(int x,int rt)
{
if(tree[rt].ans==0||tree[rt].ans==tree[rt].r-tree[rt].l+1)
return tree[rt].ans;
int mid=(tree[rt].l+tree[rt].r)>>1;
if(x<=mid)
{
if(x>=tree[rt<<1].r-tree[rt<<1].rans+1)
return tree[rt<<1].rans+tree[rt<<1|1].lans;
else return query(x,rt<<1);
}
else
{
if(x<=tree[rt<<1|1].l+tree[rt<<1|1].lans-1)
return tree[rt<<1].rans+tree[rt<<1|1].lans;
else return query(x,rt<<1|1);
}
}
int main()
{
int i,j,n,m,x;
char str[3];
while(scanf("%d%d",&n,&m)!=-1)
{
stack<int>s;
while(!s.empty()) s.pop();
build(1,n,1);
while(m--)
{
scanf("%s",str);
if(str[0]=='D')
{
scanf("%d",&x);
updata(x,1,0);
s.push(x);
}
else if(str[0]=='Q')
{
scanf("%d",&x);
printf("%d\n",query(x,1));
}
else
{
x=s.top();
s.pop();
updata(x,1,1);
}
}
}
return 0;
}

P(hdu 1542 Atlantis)扫描线求矩形面积

#include<stdio.h>
#include<string.h>
#include<stack>
#include<string>
#include<math.h>
#include<queue>
#include<set>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
using namespace std;
#define LL long long
#define inf 1<<30
#define N 210
struct node
{
int l,r;
int c;//c用来记录重叠情况
double cnt,lf,rf;
//cnt用来计算y的长度,rf,lf分别是对应的左右真实的浮点数端点
}tree[N<<2];
struct Line
{
double x,y1,y2;
int f;
}line
;
//把一段段平行于y轴的线段表示成数组 ,
//x是线段的x坐标,y1,y2线段对应的下端点和上端点的坐标
//一个矩形 ,左边的那条边f为1,右边的为-1,
//用来记录重叠情况,可以根据这个来计算,nod节点中的c
double y
;//记录y坐标的数组
bool cmp(Line a,Line b)
{
return a.x<b.x;
}
void build(int l,int r,int rt)
{
tree[rt].l=l;tree[rt].r=r;
tree[rt].cnt=tree[rt].c=0;
tree[rt].lf=y[l];tree[rt].rf=y[r];
if(l+1==r) return ;
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid,r,rt<<1|1);
}
void calen(int rt)
{
if(tree[rt].c>0)
{
tree[rt].cnt=tree[rt].rf-tree[rt].lf;
return ;
}
if(tree[rt].l+1==tree[rt].r) tree[rt].cnt=0;
else tree[rt].cnt=tree[rt<<1].cnt+tree[rt<<1|1].cnt;
}
void updata(int rt,Line e)
{
if(e.y1==tree[rt].lf&&tree[rt].rf==e.y2)
{
tree[rt].c+=e.f;
calen(rt);
return ;
}
if(e.y2<=tree[rt<<1].rf) updata(rt<<1,e);
else if(e.y1>=tree[rt<<1|1].lf) updata(rt<<1|1,e);
else
{
Line tmp=e;
tmp.y2=tree[rt<<1].rf;
updata(rt<<1,tmp);
tmp=e;
tmp.y1=tree[rt<<1|1].lf;
updata(rt<<1|1,tmp);
}
calen(rt);
}
int main()
{
int i,n,j,t,ca=1;
double x1,x2,y1,y2;
while(scanf("%d",&n),n)
{
t=1;
for(i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[t].x=x1;line[t].y1=y1;line[t].y2=y2;line[t].f=1;
y[t]=y1; t++;
line[t].x=x2;line[t].y1=y1;line[t].y2=y2;line[t].f=-1;
y[t]=y2; t++;
}
sort(line+1,line+t,cmp);
sort(y+1,y+t);
build(1,t-1,1);
updata(1,line[1]);
double ans=0;
for(i=2;i<t;i++)
{
ans+=tree[1].cnt*(line[i].x-line[i-1].x);
updata(1,line[i]);
}
printf("Test case #%d\nTotal explored area: %.2f\n\n",ca++,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: