简单线段树专辑(未完待续 poj3468+hdu1698+hdu4325+hdu1394+poj2777
2014-05-10 11:41
393 查看
最近重新学的最简单的线段树,纪念一下:(时间紧张,就不写详细的解释了,程序里重要的地方会有注释
A: Poj3468 http://poj.org/problem?id=3468
成段更新,区间求和
#include<iostream> #include<stdlib.h> #include<algorithm> #include<cmath> #include<cstdio> #include<cstring> using namespace std; #define maxn 100005 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define type __int64 type m[maxn]; type sum[maxn*3]; type lazy[maxn*3]; class Segment_tree{ private: ; public: void PushUp( int rt ){ sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void PushDown(int rt,int num){ if(lazy[rt] != 0){ lazy[rt<<1] += lazy[rt]; sum[rt<<1] += lazy[rt] * (num-num/2); lazy[rt<<1|1] += lazy[rt]; sum[rt<<1|1] += lazy[rt] * (num/2); lazy[rt] = 0; } } void build(int l,int r,int rt){ if(l == r){ sum[rt] = m[l]; lazy[rt] = 0; return; } lazy[rt] = 0;//每个线段都要初始化,注意! int mid = (l+r)>>1; build(lson); build(rson); PushUp(rt); } void update(int L,int R,int add,int l,int r,int rt){ if(L <= l && R >= r){ sum[rt] += ((type)(add))*((type)(r-l+1));//o(≧口≦)o lazy[rt] += add; return ; } PushDown(rt,r-l+1); int mid = (l+r)>>1; if(L <= mid)update(L,R,add,lson); if(R > mid)update(L,R,add,rson); PushUp(rt);//update之后不要忘记PushUp! } type query(int L,int R,int l,int r,int rt){ if(L <= l && R >= r){ return sum[rt]; } PushDown(rt,r-l+1); int mid = (l+r)>>1; type ans = 0; if(L <= mid)ans += query(L,R,lson); if(R > mid)ans += query(L,R,rson); return ans; } }; int main() { int N,M,cas=0; while(~scanf("%d",&N)){ scanf("%d",&M); for (int i = 1; i <= N; i++) scanf("%I64d",&m[i]); Segment_tree tree; tree.build(1,N,1); char s[2]={}; int l,r,add; while(M--){ scanf("%s",s); if(s[0] == 'Q'){ scanf("%d %d",&l,&r); if(l > r)swap(l,r); printf("%I64d\n",tree.query(l,r,1,N,1)); }else if(s[0] == 'C'){ scanf("%d %d %d",&l,&r,&add); if(l > r)swap(l,r); tree.update(l,r,add,1,N,1); } } } return 0; }
B: Hdu 1698 http://acm.hdu.edu.cn/showproblem.php?pid=1698
成段更新,区间求和
#include<iostream> #include<stdlib.h> #include<algorithm> #include<cmath> #include<cstdio> #include<cstring> using namespace std; #define maxn 100005 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 int m[maxn]; int sum[maxn*3]; int lazy[maxn*3]; class Segment_tree{ private: ; public: void PushUp( int rt ){ sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void PushDown(int rt,int num){ if(lazy[rt]){ lazy[rt<<1] = lazy[rt]; sum[rt<<1] = lazy[rt] * (num-num/2); lazy[rt<<1|1] = lazy[rt]; sum[rt<<1|1] = lazy[rt] * (num/2); lazy[rt] = 0; } } void build(int l,int r,int rt){ if(l == r){ sum[rt] = 1; lazy[rt] = 0; return; } lazy[rt] = 0;//每个线段都要初始化,注意! int mid = (l+r)>>1; build(lson); build(rson); PushUp(rt); } void update(int L,int R,int add,int l,int r,int rt){ if(L <= l && R >= r){ sum[rt] = add*(r-l+1); lazy[rt] = add; return ; } PushDown(rt,r-l+1); int mid = (l+r)>>1; if(L <= mid)update(L,R,add,lson); if(R > mid )update(L,R,add,rson); PushUp(rt);//update之后不要忘记PushUp! } int query(int L,int R,int l,int r,int rt){ if(L <= l && R >= r){ return sum[rt]; } int mid = (l+r)>>1; int ans = 0; if(L <= mid)ans += query(L,R,lson); if(R > mid)ans += query(L,R,rson); return ans; } }; int main() { int T,N,M,cas=0; scanf("%d",&T); for(int i=0;i<T;i++){ scanf("%d %d",&N,&M); //for (int i = 1; i <= N; i++) scanf("%d",&m[i]); Segment_tree tree; tree.build(1,N,1); int l,r,_new; for (int i = 0; i < M; i++) { scanf("%d%d%d",&l,&r,&_new); tree.update(l,r,_new,1,N,1); } printf("Case %d: The total value of the hook is %d.\n",++cas,sum[1]); } return 0; }
C: Hdu4325 http://acm.hdu.edu.cn/showproblem.php?pid=4325
#include<iostream> #include<stdlib.h> #include<algorithm> #include<cmath> #include<cstdio> #include<cstring> #include<map> using namespace std; #define maxn 400005 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define type int type m[maxn]; type sum[maxn*3]; type lazy[maxn*3]; class Segment_tree{ private: ; public: void PushUp( int rt ){ sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void PushDown(int rt,int num){ if(lazy[rt] != 0){ lazy[rt<<1] += lazy[rt]; sum[rt<<1] += lazy[rt] * (num-num/2); lazy[rt<<1|1] += lazy[rt]; sum[rt<<1|1] += lazy[rt] * (num/2); lazy[rt] = 0; } } void build(int l,int r,int rt){ if(l == r){ sum[rt] = 0; lazy[rt] = 0; return; } lazy[rt] = 0;//每个线段都要初始化,注意! int mid = (l+r)>>1; build(lson); build(rson); PushUp(rt); } void update(int L,int R,int add,int l,int r,int rt){ if(L <= l && R >= r){ sum[rt] += ((type)(add))*((type)(r-l+1));//o(≧口≦)o lazy[rt] += add; return ; } PushDown(rt,r-l+1); int mid = (l+r)>>1; if(L <= mid)update(L,R,add,lson); if(R > mid)update(L,R,add,rson); PushUp(rt);//update之后不要忘记PushUp! } type query(int L,int R,int l,int r,int rt){ if(L <= l && R >= r){ return sum[rt]; } PushDown(rt,r-l+1); int mid = (l+r)>>1; type ans = 0; if(L <= mid)ans += query(L,R,lson); if(R > mid)ans += query(L,R,rson); return ans; } }; int ne[maxn],l[maxn],r[maxn],q[maxn]; int main() { int T,N,M,cas=0,ind; scanf("%d",&T); while(T--){ scanf("%d",&N); scanf("%d",&M); ind = 0; for (int i = 1; i <= N; i++){ scanf("%d %d",&l[i],&r[i]); ne[ind++] = l[i]; ne[ind++] = r[i]; } for (int i = 1; i <= M; i++) { scanf("%d",&q[i]); ne[ind++] = q[i]; } //去重 sort(ne,ne+ind); int newind = unique(ne,ne+ind) - ne; map<int,int>mapp; for (int i = 1; i <= newind; i++) { mapp[ne[i-1]] = i;//用map的去重方法,( ^_^ )不错嘛, } Segment_tree tree; tree.build(1,newind,1); for (int i = 1; i <= N; i++) { tree.update(mapp[l[i]],mapp[r[i]],1,1,newind,1); } printf("Case #%d:\n",++cas); for (int i = 1; i <= M; i++) { printf("%d\n",tree.query(mapp[q[i]],mapp[q[i]],1,newind,1)); } } return 0; }
E: Hdu1394 http://acm.hdu.edu.cn/showproblem.php?pid=1394
#include<iostream> #include<stdlib.h> #include<algorithm> #include<cmath> #include<cstdio> #include<cstring> #include<map> using namespace std; #define maxn 5005 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define type int int a[maxn]; type sum[maxn*3]; type lazy[maxn*3]; class Segment_tree{ private: ; public: void PushUp( int rt ){ sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void PushDown(int rt,int num){ if(lazy[rt] != 0){ lazy[rt<<1] += lazy[rt]; sum[rt<<1] += lazy[rt] * (num-num/2); lazy[rt<<1|1] += lazy[rt]; sum[rt<<1|1] += lazy[rt] * (num/2); lazy[rt] = 0; } } void build(int l,int r,int rt){ if(l == r){ sum[rt] = 0; lazy[rt] = 0; return; } lazy[rt] = 0;//每个线段都要初始化,注意! int mid = (l+r)>>1; build(lson); build(rson); PushUp(rt); } void update(int L,int R,int add,int l,int r,int rt){ if(L <= l && R >= r){ sum[rt] += ((type)(add))*((type)(r-l+1));//o(≧口≦)o lazy[rt] += add; return ; } PushDown(rt,r-l+1); int mid = (l+r)>>1; if(L <= mid)update(L,R,add,lson); if(R > mid)update(L,R,add,rson); PushUp(rt);//update之后不要忘记PushUp! } type query(int L,int R,int l,int r,int rt){ if(L <= l && R >= r){ return sum[rt]; } PushDown(rt,r-l+1); int mid = (l+r)>>1; type ans = 0; if(L <= mid)ans += query(L,R,lson); if(R > mid)ans += query(L,R,rson); return ans; } }; int main(){ int N; Segment_tree tree; while(~scanf("%d",&N)){ tree.build(0,N-1,1); int sum = 0; for (int i = 0; i < N; i++) { scanf("%d",&a[i]); sum += tree.query(a[i],N-1,0,N-1,1);//询问从a[i]到n-1一共有多少个一,即逆序数 tree.update(a[i],a[i],1,0,N-1,1);//在a[i]位置添上一。 } int ans = sum; // printf("%d\n",ans); for (int i = 0; i < N; i++) { sum += (-a[i] +(N-1 - a[i])); //a[i]即是原数列中a[i]之后比a[i]小的数目,n-1-a[i]反之 ans = min(ans,sum); } printf("%d\n",ans); } return 0; }
F: Poj2777 http://poj.org/problem?id=2777
#include<iostream> #include<stdlib.h> #include<algorithm> #include<cmath> #include<cstdio> #include<cstring> #include<map> using namespace std; #define maxn 100005 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define type long long #define LL long long int a[maxn]; type sum[maxn*3]; int lazy[maxn*3]; class Segment_tree{ private: ; public: void PushUp( int rt ){ sum[rt] = sum[rt<<1] | sum[rt<<1|1]; } void PushDown(int rt,int num){ if(lazy[rt] != 0){ lazy[rt<<1] = lazy[rt]; sum[rt<<1] = (1LL<<(lazy[rt]-1)) ; lazy[rt<<1|1] = lazy[rt]; sum[rt<<1|1] = (1LL<<(lazy[rt]-1)) ; lazy[rt] = 0; } } void build(int l,int r,int rt){ if(l == r){ sum[rt] = 1; lazy[rt] = 0; return; } lazy[rt] = 0;//每个线段都要初始化,注意! int mid = (l+r)>>1; build(lson); build(rson); PushUp(rt); } void update(int L,int R,int add,int l,int r,int rt){ if(L <= l && R >= r){ sum[rt] = (1LL<<(add-1));//o(≧口≦)o lazy[rt] = add; return ; } PushDown(rt,r-l+1); int mid = (l+r)>>1; if(L <= mid)update(L,R,add,lson); if(R > mid)update(L,R,add,rson); PushUp(rt);//update之后不要忘记PushUp! } type query(int L,int R,int l,int r,int rt){ if(L <= l && R >= r){ return sum[rt]; } PushDown(rt,r-l+1); int mid = (l+r)>>1; type ans = 0; if(L <= mid)ans |= query(L,R,lson); if(R > mid)ans |= query(L,R,rson); return ans; } }; int one(LL x){ if(x == 0)return 0; int n = 1; while(x & (x-1)){ x = x&(x-1); n++; } return n; } int main(){ int L,T,O; Segment_tree tree; int l,r,color; LL ans = 0; while(~scanf("%d%d%d",&L,&T,&O)){ tree.build(1,L,1); char tmp[2]={}; while(O--){ scanf("%s",tmp); if(tmp[0] == 'C'){ scanf("%d %d %d",&l,&r,&color); if(l>r)swap(l,r); tree.update(l,r,color,1,L,1); }else if(tmp[0] == 'P'){ scanf("%d %d",&l,&r); if(l>r)swap(l,r); ans = tree.query(l,r,1,L,1); //printf("%lld\n",ans); printf("%d\n",one(ans)); } } } return 0; }
H:
成段更新求最值
#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
#define maxn 22222
//不算边界上的,所以用段做线段树
#define lson l,mid,rt<<1
#define rson mid,r,rt<<1|1
double x[maxn];
struct segment{
double l,r,h;
int bri;
void set(double a,double b,double c,int d){
l=a,r=b,h=c,bri=d;
}
bool operator <(const segment & d)const{
if(d.h == h)return bri < d.bri;//不算边界,就先加下边,后加上边
return h < d.h;
}
}s[maxn*2];
int cover[maxn<<2];
int sum[maxn<<2];
class Segment_tree{
public:
void PushUp(int rt){
sum[rt] = max(sum[rt<<1] , sum[rt<<1|1]);
}
void PushDown(int rt){
if(cover[rt]){
cover[rt<<1] += cover[rt];
sum[rt<<1] += cover[rt];
cover[rt<<1|1] += cover[rt];
sum[rt<<1|1] += cover[rt];
cover[rt] = 0;
}
}
void update(int L,int R,int add,int l,int r,int rt){
if(L<=l && r<=R){
sum[rt] += add;
cover[rt] += add;
return ;
}
PushDown(rt);
int mid = (l+r)>>1;
if(l == r-1)return ;//不加可能会死循环
if(L <= mid)update(L,R,add,lson);
if(R > mid)update(L,R,add,rson);
PushUp(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L <= l && R >= r){
return sum[rt];
}
PushDown(rt);
int mid = (l+r)>>1;
int ans = 0;
if(L <= mid)ans = max(ans,query(L,R,lson));
if(R > mid)ans = max(ans,query(L,R,rson));
return ans;
}
};
int main(){
int cas=1,n,i,j,k;
double a,b,w,h;int bri;
while(~scanf("%d %lf %lf",&n,&w,&h) && n){
for (j=1, i = 0,k=0; i < n; i++)
{
scanf("%lf %lf %d",&a,&b,&bri);
s[j++].set(a,a+w,b,bri);
s[j++].set(a,a+w,b+h,-bri);
x[k++] = a;
x[k++] = a+w;
}
//给x坐标排序去重
sort(x,x+k);
int newk = unique(x,x+k)-x;
map<double,int> mapx;
for (int i = 1; i <= newk; i++)
mapx[x[i-1]] = i;
//对线段排序
sort(s+1,s+j);
Segment_tree tree;
//tree.build(1,newk,1);
memset(sum,0,sizeof(sum));
memset(cover,0,sizeof(cover));
int ans = 0;
for (int i = 1; i < j; i++)
{
tree.update(mapx[s[i].l],mapx[s[i].r],s[i].bri,1,newk,1);
ans = max(ans,sum[1]);
}
printf("%d\n",ans);
}
return 0;
}
I:
#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
#define maxn 20005
#define lson l,mid,rt<<1
#define rson mid,r,rt<<1|1
struct segment{
int l,r,h;
int flag;
void set(int a,int b,int c,int x){
l=a,r=b,h=c;
flag = x;
}
bool operator <(const segment & d)const{
if(d.h == h)return flag > d.flag;
return h < d.h;
}
}s[maxn*2];
int x[maxn];
int cover[maxn<<2];
int sum[maxn<<2];
int num[maxn<<2];//竖线的数目
bool ld[maxn<<2],rd[maxn<<2];
class Segment_tree{
public:
void PushUp(int l,int r,int rt){
if(cover[rt]) {
sum[rt] = x[r-1] - x[l-1];
ld[rt] = rd[rt] = 1;
num[rt] = 2;
}else{
ld[rt] = ld[rt<<1];
rd[rt] = rd[rt<<1|1];
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
num[rt] = num[rt<<1] + num[rt<<1|1];
if(ld[rt<<1|1] && rd[rt<<1])//边界重合
num[rt]-=2;
}
}
void build(int l,int r,int rt){
if(l == r-1){
sum[rt] = 0;
cover[rt] = 0;
ld[rt] = rd[rt] = 0;
num[rt] = 0;
return ;
}
int mid = (l+r)>>1;
build(lson);
build(rson);
PushUp(l,r,rt);
}
void update(int L,int R,int add,int l,int r,int rt){
if(L<=l && r<=R){
cover[rt] += add;
PushUp(l,r,rt);
return ;
}
int mid = (l+r)>>1;
if(l == r-1)return;
if(L <= mid)update(L,R,add,lson);
if(R > mid)update(L,R,add,rson);
PushUp(l,r,rt);
}
};
int main(){
int cas=1,n,i,j,k;
int a,b,c,d;
while(~scanf("%d",&n) && n){
for (j=1,i=0,k=0; i < n; i++)
{
scanf("%d %d %d %d",&a,&b,&c,&d);
x[k++]=a;
x[k++]=c;
s[j++].set(a,c,b,1);
s[j++].set(a,c,d,-1);
}
sort(x,x+k);
int newk = unique(x,x+k)-x;
map<int ,int >mx;
for ( i = 1; i <= newk; i++)
mx[x[i-1]] = i;
sort(s+1,s+j);
Segment_tree tree;
tree.build(1,newk,1);
int ans = 0,pre = 0;
tree.update(mx[s[1].l],mx[s[1].r],s[1].flag,1,newk,1);
int height = 0;
for ( i = 2; i < j; i++)
{
height = s[i].h - s[i-1].h;
ans += abs(sum[1] - pre);
ans += num[1] * height;
pre = sum[1];
tree.update(mx[s[i].l],mx[s[i].r],s[i].flag,1,newk,1);
}
ans += abs(sum[1] - pre);
printf("%d\n",ans);
}
return 0;
}
相关文章推荐
- 【数据结构】线段树专辑
- 简单线段树总结
- hdu 1166 敌兵布阵(简单线段树or树状数组)
- 线段树的简单应用
- 线段树简单实现
- hdu4339 Query(简单线段树)
- bzoj3155 Preprefix sum(简单线段树)
- 线段树专辑——pku 2528 Mayor's posters
- Just a Hook(HDU1698 线段树的简单应用)
- 【数据结构】线段树专辑
- 【线段树】【重庆省选2006】简单题 easy
- poj 2528 Mayor's posters 简单离散化+线段树
- 线段树之简单方法
- hdu1556 线段树段更新(简单题)
- HDU-1754-I Hate It(线段树,简单,不过好像有点问题)
- hdu4614 Vases and Flowers (简单线段树 + 二分)
- bzoj 1012 简单的线段树
- HDU 1754 ——简单线段树
- 线段树的简单应用;火车订票;线段树用起来太灵活了!;
- 线段树专辑——hdu 1698 Just a Hook