[kuangbin帶你飛]專題七 線段樹
阿新 • • 發佈:2019-01-30
A(hdu 1166 敵兵佈陣 )中文體面,線段樹單點更新,求一段區間和
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 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; }
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 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; }
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 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; }
#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[N];
int key[N],tot,ans;
bool mark[N];
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[N],ans[N];//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[N];
//把一段段平行於y軸的線段表示成陣列 ,
//x是線段的x座標,y1,y2線段對應的下端點和上端點的座標
//一個矩形 ,左邊的那條邊f為1,右邊的為-1,
//用來記錄重疊情況,可以根據這個來計算,nod節點中的c
double y[N];//記錄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;
}