hdu4973 线段树
来源:互联网 发布:网络推广广告 编辑:程序博客网 时间:2024/06/04 19:14
题意:给定的序列 有两个操作 1将其中一段加倍 2询问段中的最长相等数字是多少
解法:直接上线段树就可以了 但是-》边界问题比较麻烦 有两种做法 一种在更新的时候直接判定边界,另外一种则是选定完边界再进行更新,题解的说法里面是第二种啊,但是比赛的时候不敢敲,怕码力不够啊。有点后悔的
首先是麻烦的写法:
#include<cstdio>#include<iostream>#include<algorithm>using namespace std;#define ls (rt<<1)#define rs (rt<<1|1)#define mid ((l+r)>>1)#define ll __int64#define maxn 55555ll sum[maxn<<2],mul[maxn<<2],ma[maxn<<2];void up(int rt,int l,int r){ sum[rt]=sum[ls]+sum[rs]; ma[rt]=max(ma[ls],ma[rs]);}void down(int rt,int l,int r){ if(mul[rt]){ sum[ls]<<=mul[rt]; sum[rs]<<=mul[rt]; ma[ls]<<=mul[rt]; ma[rs]<<=mul[rt]; mul[ls]+=mul[rt]; mul[rs]+=mul[rt]; mul[rt]=0; }}void build(int rt,int l,int r){ mul[rt]=0; if(l==r){ sum[rt]=ma[rt]=(ll)1; return ; } build(ls,l,mid); build(rs,mid+1,r); up(rt,l,r);}int queryl(int rt,int l,int r,ll w){ if(l==r)return l; down(rt,l,r); if(sum[ls]>=w){ return queryl(ls,l,mid,w); }else return queryl(rs,mid+1,r,w-sum[ls]);}void ins(int rt,int l,int r,int L,int R){ if(L<=l&&r<=R){ sum[rt]<<=1; ma[rt]<<=1; mul[rt]++; return ; }down(rt,l,r); if(L<=mid)ins(ls,l,mid,L,R); if(mid<R)ins(rs,mid+1,r,L,R); up(rt,l,r);}void ins_s(int rt,int l,int r,int L,int R,ll w){ if(L<=l&&r<=R){ sum[rt]+=w; ma[rt]+=w; return ; }down(rt,l,r); if(L<=mid)ins_s(ls,l,mid,L,R,w); if(mid<R)ins_s(rs,mid+1,r,L,R,w); up(rt,l,r);}ll querys(int rt,int l,int r,int L,int R){ if(L<=l&&r<=R){ return sum[rt]; }down(rt,l,r); ll res=0; if(L<=mid)res+=querys(ls,l,mid,L,R); if(mid<R)res+=querys(rs,mid+1,r,L,R); return res;}ll query(int rt,int l,int r,int L,int R){ if(L<=l&&r<=R)return ma[rt]; down(rt,l,r); ll res=0; if(L<=mid)res=max(res,query(ls,l,mid,L,R)); if(mid<R)res=max(res,query(rs,mid+1,r,L,R)); return res;}int n,m;char op[111];int main(){ int _;scanf("%d",&_); for(int z=1;z<=_;++z){ scanf("%d%d",&n,&m); build(1,1,n);ll l,r; printf("Case #%d:\n",z); while(m--){ scanf("%s%I64d%I64d",op,&l,&r); if(l>r)swap(l,r); int lf=queryl(1,1,n,l); int ri=queryl(1,1,n,r); ll lsum=querys(1,1,n,1,lf),rsum; if(ri>1)rsum=querys(1,1,n,1,ri-1); else rsum=0; // printf("%d %d %lld %lld\n",lf,ri,lsum,rsum); if(*op=='D'){ if(lf==ri){ ins_s(1,1,n,lf,lf,r-l+1); }else{ if(lf+1<=ri-1)ins(1,1,n,lf+1,ri-1); ins_s(1,1,n,lf,lf,lsum-l+1); ins_s(1,1,n,ri,ri,r-rsum); } } else{ if(lf==ri){ printf("%I64d\n",r-l+1); }else{ ll maxx=0; if(lf+1<=ri-1)maxx=max(maxx,query(1,1,n,lf+1,ri-1)); maxx=max(maxx,lsum-l+1); maxx=max(maxx,r-rsum); printf("%I64d\n",maxx); } } } } return 0;}
其次是比较简洁的:
#include<cstdio>#include<iostream>#include<algorithm>using namespace std;#define ls (rt<<1)#define rs (rt<<1|1)#define mid ((l+r)>>1)#define ll __int64#define maxn 55555int scan(){ int res=0,ch; while(!((ch= getchar())>='0'&&ch<='9')){ if(ch==EOF)return 1<<30; } res=ch-'0'; while((ch=getchar())>='0'&&ch<='9') res=res*10+(ch-'0'); return res;}ll sum[maxn<<2],mul[maxn<<2],ma[maxn<<2];void up(int rt,int l,int r){ sum[rt]=sum[ls]+sum[rs]; ma[rt]=max(ma[ls],ma[rs]);}void down(int rt,int l,int r){ if(mul[rt]){ sum[ls]<<=mul[rt]; sum[rs]<<=mul[rt]; ma[ls]<<=mul[rt]; ma[rs]<<=mul[rt]; mul[ls]+=mul[rt]; mul[rs]+=mul[rt]; mul[rt]=0; }}void build(int rt,int l,int r){ mul[rt]=0; if(l==r){ sum[rt]=ma[rt]=(ll)1; return ; } build(ls,l,mid); build(rs,mid+1,r); up(rt,l,r);}void insr(int rt,int l,int r,ll L,ll R){ if(l==r){ ma[rt]=sum[rt]+=R-L+1; return ; }else if(R-L+1==sum[rt]){ sum[rt]<<=1;ma[rt]<<=1;mul[rt]++; return ; }down(rt,l,r); if(sum[ls]>=R)insr(ls,l,mid,L,R); else if(sum[ls]<L)insr(rs,mid+1,r,L-sum[ls],R-sum[ls]); else{ insr(rs,mid+1,r,1,R-sum[ls]); insr(ls,l,mid,L,sum[ls]); } up(rt,l,r);}ll queryr(int rt,int l,int r,ll L,ll R){ if(l==r)return R-L+1 ; if(R-L+1==sum[rt])return ma[rt]; down(rt,l,r); if(sum[ls]>=R)return queryr(ls,l,mid,L,R); if(sum[ls]<L)return queryr(rs,mid+1,r,L-sum[ls],R-sum[ls]); return max(queryr(ls,l,mid,L,sum[ls]),queryr(rs,mid+1,r,1,R-sum[ls]));}int n,m;char op[111];int main(){ int _;scanf("%d",&_); for(int z=1;z<=_;++z){ scanf("%d%d",&n,&m); build(1,1,n);ll l,r; printf("Case #%d:\n",z); while(m--){ scanf("%s%I64d%I64d",op,&l,&r); if(*op=='D'){ insr(1,1,n,l,r); } else{ printf("%I64d\n",queryr(1,1,n,l,r)); } } } return 0;}
0 0
- hdu4973(线段树)
- hdu4973 线段树
- hdu4973 线段树
- hdu4973 A simple simulation problem. 线段树
- HDU4973:A simple simulation problem.(线段树)
- hdu4973
- hdu4973 线段树(题目不错,用了点,段,更新查找还有DFS)
- 线段树单点更新+成段更新(好)hdu4973(多校联合)
- 2014多校10(1003)hdu4973(简单线段树区间操作)
- HDU4973 【几何。】
- HDU4973 A simple simulation problem.
- HDU4973 A simple simulation problem
- 线段树?线段树!
- 线段树?线段树!
- 线段_线段树
- 线段_线段树
- 线段树
- 线段树
- 【第一遍机房收费系统】——实践+提升
- MFC程序对文件的处理方法
- 东软学习,一个简易改良版计算器
- cocos2dx3.0 对象池
- PHP+MYSQL会员系统的开发实例教程
- hdu4973 线段树
- [Lua]mac 上安装lua
- PHP+MYSQL会员系统的开发实例教程
- 正则表达式(括号)、[中括号]、{大括号}的区别小结
- 一种stm32架构
- AC自动机模板 LA4670
- fzoj 1319 Blocks of Stones(DP:水题)
- 11gr2 RAC安装INS-35354问题,remote节点识别不了
- 分治法求数组最大连续子序列的和