线段树(堆式)[区间更新]
来源:互联网 发布:东莞seo外包 编辑:程序博客网 时间:2024/05/20 08:22
区间更新是个坎。。。 堆式的区间更新是个大坎。。。
hdu1698 Just a Hook
解法1 还没理解自底向上的更新方法, 还是自顶向下的递归更新, 跑了859ms,悲剧。。。
代码很丑, 不过自创了一个debug函数,可以看树的结构, 不错,不错。
#include <cstdio>#include <string.h>#include <algorithm>using namespace std;typedef long long ll;const int maxn=100000+123;int T[maxn*3];int M, h;int bit(int x)/// get highest 1 in bit-number{ if(x==0)return 0; int n=31; if((x>>16)==0){n-=16; x<<=16;} if((x>>24)==0){n-=8; x<<=8;} if((x>>28)==0){n-=4; x<<=4;} if((x>>30)==0){n-=2; x<<=2;} return n-(x>>31);}inline void merge (const int &x)//合并2个儿子的信息{ if(T[x]==0 && T[x<<1]==T[x<<1|1])T[x]=T[x<<1];}void init(const int & x){ h=bit(x); M=1<<h; memset (T, 0, sizeof(T)); for (int i=M; i<x+M; ++i) T[i]=1; for (int i=M-1; i>0; --i) merge(i);}void Updata(int x, int v){ T[x]=v; if(x<M) { T[x<<1]=v; T[x<<1|1]=v; }}void color (int l, int r, int x, int root){ if(T[root]==x)return ; if(root>M+M)return; if(root>=M){if(root>l && root<r)T[root]=x; return;} int t=h-bit(root)+1; if((l>>t)<root && (r>>t)>root) T[root]=x; else { if(T[root]){T[root<<1]=T[root]; T[root<<1|1]=T[root]; T[root]=0;} if((l>>(t-1))<=(root<<1))color(l, r, x, root<<1); if((r>>(t-1))>=(root<<1|1))color(l, r, x, root<<1|1); }}inline void Change(int l, int r, int x){ color (l+M-1, r+M+1, x, 1);}int getson (int x){ if(x>=M)return T[x]; if(T[x]) { int t=h-bit(x)+1; return (1<<t)*T[x]; } return getson(x<<1)+getson(x<<1|1);}int Request (int l, int r){ return getson(1);}void debug(int n){ for (int i=1; i<M+n; ++i) printf("%d%c", T[i], ((i^1)&&(i^3)&&(i^7)&&(i^15)&&(i^31)&&(i^63))?' ':'\n'); puts("");}int main (){ int cas; scanf("%d", &cas); for (int I=1; I<=cas; ++I) { int n, k; scanf("%d", &n); init(n); scanf("%d", &k); while (k--) { int s, t, v; scanf("%d%d%d", &s, &t, &v); Change(s-1, t-1, v); //debug(n); } printf("Case %d: The total value of the hook is %d.\n", I, Request(0, n-1)); } return 0;}
poj2528 Mayor’s posters
题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报
这个区间的离散化很重要
#include <cstdio>#include <string.h>#include <algorithm>using namespace std;typedef long long ll;const int maxn=100000+123;int T[maxn*3];int M, h;int bit(int x)/// get highest 1 in bit-number{ if(x==0)return 0; int n=31; if((x>>16)==0){n-=16; x<<=16;} if((x>>24)==0){n-=8; x<<=8;} if((x>>28)==0){n-=4; x<<=4;} if((x>>30)==0){n-=2; x<<=2;} return n-(x>>31);}void init(int x){ h=bit(x); M=1<<h; memset (T, 0, sizeof(T));}inline void Updata(const int & x, const int & v){ T[x]=v;}void Down (int l, int r)// 区间下传信息, 实际上只是对2个开区间边界下传信息{ for (int i=h; i>0; --i) { int ll=l>>i, rr=r>>i; if(T[ll]) { T[ll<<1]=T[ll<<1|1]=T[ll]; } if(T[rr]) { T[rr<<1]=T[rr<<1|1]=T[rr]; } T[ll]=T[rr]=0; }}void Interval_Updata(int l, int r, int x){ int t=1; for (l+=M-1, r+=M+1, Down(l, r); l^r^1; l>>=1, r>>=1, t<<=1) { if(~l&1) Updata(l^1, x); if( r&1) Updata(r^1, x); }}void debug(int n){ for (int i=1; i<M+n; ++i) printf("%d%c", T[i], ((i^1)&&(i^3)&&(i^7)&&(i^15)&&(i^31)&&(i^63))?' ':'\n'); puts("");}bool flag[maxn];int ans;void Request (int x){ if(T[x]) { if(flag[T[x]])return; ans++; flag[T[x]]=true; return; } if(x<M) { Request(x<<1); Request(x<<1|1); }}int l[maxn], r[maxn];int X[maxn];int cnt;int bin(int x){ int low=0, high=cnt, mid; while (low<=high) { mid=(low+high)>>1; //printf("%d %d %d %d %d\n", low, high, mid, X[mid], x); if(X[mid]==x)return mid; if(X[mid]<x)low=mid+1; if(X[mid]>x)high=mid-1; }}int main (){ int cas, n; scanf("%d", &cas); while (cas--) { scanf("%d", &n); int cnt1=0, cnt2=1; for (int i=0; i<n; ++i) { scanf("%d%d", l+i, r+i); X[cnt1++]=l[i]; X[cnt1++]=r[i]; } sort(X, X+cnt1); for (int i=1; i<cnt1; ++i)//去重 if(X[i]!=X[i-1])X[cnt2++]=X[i]; cnt1=cnt2; for (int i=1; i<cnt1; ++i) //加间隔,因为这里的节点表示的是区间,离散量之间没有一个中点会出现 //1-10 1-4 5-10和1-10 1-4 6-10答案都是2的情况,但实际上第二个答案是3 if(X[i]>X[i-1]+1)X[cnt2++]=X[i-1]+1; sort(X, X+cnt2); cnt=cnt2; init(cnt); //debug(n); for (int i=0; i<n; ++i) { int ll=bin(l[i]), rr=bin(r[i]); Interval_Updata(ll, rr, i+1); //printf("l=%d r=%d %d %d\n", ll, rr, l[i], r[i]); //debug(cnt); } memset (flag, 0, sizeof(flag)); ans=0; Request(1); printf("%d\n", ans); } return 0;}
http://poj.org/problem?id=3468
区间加减, 区间求和
#include <cstdio>#include <string.h>#include <algorithm>using namespace std;typedef long long ll;const int maxn=100000+123;ll T[maxn*3];ll flag[maxn*3];int M, h;int bit(int x)/// get highest 1 in bit-number{ if(x==0)return 0; int n=31; if((x>>16)==0){n-=16; x<<=16;} if((x>>24)==0){n-=8; x<<=8;} if((x>>28)==0){n-=4; x<<=4;} if((x>>30)==0){n-=2; x<<=2;} return n-(x>>31);}void merge (const int &x)// 合并子节点的信息到父亲{ T[x]=T[x<<1]+T[x<<1|1];}void init(const int &x){ h=bit(x); M=1<<h; memset (T, 0, sizeof(T)); memset (flag, 0, sizeof(flag)); for (int i=0; i<x; ++i) scanf("%lld", T+i+M); for (int i=M-1; i>0; --i) merge(i);}void Down(const int &k)// 下传标记并对当前标记清除{ for (int i=h; i>0; --i) { int p=k>>i; flag[p<<1]+=flag[p]; flag[p<<1|1]+=flag[p]; T[p<<1]+=flag[p]*(1ll<<i-1); T[p<<1|1]+=flag[p]*(1ll<<i-1); flag[p]=0; }}void Updata(int x, int v, int w)//更新节点{ flag[x]+=v; T[x]+=(ll)v*(ll)w;}void Interval_Updata(int l, int r, int v)//区间更新, 先下传, 再更新 再合并{ int t=1; for (l+=M-1, r+=M+1, Down(l), Down(r); l^r^1; r>>=1, l>>=1, merge(r), merge(l), t<<=1) { if(~l&1) Updata(l^1, v, t); if( r&1) Updata(r^1, v, t); } while (l>1) { l>>=1; r>>=1; merge(l); if(l^r)merge(r); }}ll Request (int l, int r)// 区间查询, 先下传, 再查询{ ll res=0; for (l+=M-1, r+=M+1, Down(l), Down(r); l^r^1; l>>=1, r>>=1) { if(~l&1)res+=T[l^1]; if( r&1)res+=T[r^1]; } return res;}void debug(int n)//你懂的{ for (int i=1; i<M+n; ++i) printf("%lld%c", T[i], ((i^1)&&(i^3)&&(i^7)&&(i^15)&&(i^31)&&(i^63))?' ':'\n'); puts("");}int main (){ char op[5]; int n, q, s, t, w; while (~scanf("%d%d", &n, &q)) { init(n); while(q--) { scanf("%s", op); if(op[0]=='Q') { scanf("%d%d", &s, &t); printf("%lld\n", Request(s-1, t-1)); } if(op[0]=='C') { scanf("%d%d%d", &s, &t, &w); Interval_Updata(s-1, t-1, w); } } } return 0;}/*10 101 2 3 4 5 6 7 8 9 10C 1 4 1000000000Q 1 10Q 2 4C 3 6 3Q 2 4Q 1 10C 1 10 2Q 1 10C 1 10 -2Q 1 10*/
- 线段树(堆式)[区间更新]
- 线段树(堆式)[单点更新, 区间查询]
- 线段树区间更新
- 线段树区间更新
- 线段树 区间更新
- 线段树区间更新
- 线段树-区间更新
- 线段树区间更新
- 线段树区间更新
- 线段树区间更新
- 区间更新线段树
- 线段树区间更新
- 线段树 区间更新
- 线段树区间更新
- poj2991 线段树区间更新
- poj3667 线段树区间更新
- HDU1698线段树区间更新
- hdu4031(线段树+区间更新)
- linux进程间通信-匿名半双工管道
- 轻松学—操作系统之进程
- 内存管理之memory.c
- Git 中文教程
- Android Market 账号注册和应用发布教程
- 线段树(堆式)[区间更新]
- gridview运用
- 基于嵌入式Linux视频采集系2----系统需求分析
- 28 HTML5 Features, Tips, and Techniques you Must Know
- Linux下解压命令大全 解压缩 tar bz2 zip tar.gz gz
- poj 3414 Pots
- 社会观念亟待扭转 不可忽视劳动和劳动者的价值
- Linux驱动中的platform
- 函数返回类型为指针类型时的一些问题