hdu4973(线段树)
来源:互联网 发布:php 整数保留2位小数 编辑:程序博客网 时间:2024/06/06 03:25
题意:给1-n的数字,m次操作,每次操作将区间[l,r]中的数字翻倍,比如1,2,3,4,5,D 2,3,得到的结果是1,2,2,3,3,4,5, 求区间[l,r]中同一个数字出现的最多次数
解题思路:自己AC的一道线段树,感觉很不错。以[1,n]建立线段树,线段树中维护三个信息,max即当前区间内该区间内同一个数字出现的最多次数,sum即当前区间内数字的总个数,flag延迟标记。对于每次操作,找到对应的数字 和 出现的位置,然后进行更新和查询
代码如下:
#include<iostream>#include<algorithm>#include<cstring>#include<string>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#include<math.h>#define LL __int64#define N 50005#define inf 0x7ffffff#define eps 1e-9#define pi acos(-1.0)using namespace std;struct node{ int l,r,flag; LL sum,max;}tree[N<<2];void PushUp(int o){ tree[o].sum = tree[2*o].sum + tree[2*o+1].sum; tree[o].max = max(tree[2*o].max,tree[2*o+1].max);}void build(int o,int l,int r){ tree[o].l = l; tree[o].r = r; tree[o].flag = 0; tree[o].max = 1; if(l == r) { tree[o].sum = 1; return; } int m = (l+r)/2; build(2*o,l,m); build(2*o+1,m+1,r); PushUp(o);}void PushDown(int o){ if(tree[o].flag) { tree[2*o].flag += tree[o].flag; tree[2*o+1].flag += tree[o].flag; for(int i = 0; i < tree[o].flag; i++)//一开始因为这里wa了好多次 { tree[2*o].max *= 2; tree[2*o+1].max *= 2; tree[2*o].sum *= 2; tree[2*o+1].sum *= 2; } tree[o].flag = 0; }}int find(int o,LL x,LL &k,LL &tmp){ if(tree[o].l == tree[o].r) { k = x; tmp = tree[o].sum; return tree[o].l; } PushDown(o); if(x <= tree[2*o].sum) return find(2*o,x,k,tmp); else return find(2*o+1,x-tree[2*o].sum,k,tmp);}void update1(int o,int pos,LL v)//单点更新{ if(tree[o].l == tree[o].r) { tree[o].max += v; tree[o].sum += v; return; } PushDown(o); int m = (tree[o].l + tree[o].r)/2;; if(pos <= m) update1(2*o,pos,v); else update1(2*o+1,pos,v); PushUp(o);}void update2(int o,int x,int y)//区间更新{ if(x <= tree[o].l && tree[o].r <= y) { PushDown(o); tree[o].flag++; tree[o].max *= 2; tree[o].sum *= 2; return; } PushDown(o); int m = (tree[o].l+tree[o].r)/2; if(x <= m) update2(2*o,x,y); if(y > m) update2(2*o+1,x,y); PushUp(o);}LL res;void query(int o,int x,int y){ if(x <= tree[o].l && tree[o].r <= y) { if(res < tree[o].max) res = tree[o].max; return; } PushDown(o); int m = (tree[o].l + tree[o].r)/2; if(x <= m) query(2*o,x,y); if(y > m) query(2*o+1,x,y);}void output(int o){ cout<<tree[o].l<<" "<<tree[o].r<<" "<<tree[o].max<<" "<<tree[o].sum<<endl; if(tree[o].l == tree[o].r) return; output(2*o); output(2*o+1);}int main(){//freopen("input.txt","r",stdin);//freopen("output.txt","w",stdout); int t,ca = 1; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); build(1,1,n); printf("Case #%d:\n",ca++); while(m--) { char str[2]; LL x,y; LL lk,rk; scanf("%s%I64d%I64d",str,&x,&y); LL tmp; int r = find(1,y,rk,tmp);//找数字r,出现的位置rk,该数字总的个数tmp int l = find(1,x,lk,tmp); //cout<<l<<" "<<lk<<" "<<tmp<<endl; if(str[0] == 'D') { if(l == r) { update1(1,l,rk-lk+1); continue; } update1(1,r,rk); update1(1,l,tmp-lk+1); if(r - l > 1) update2(1,l+1,r-1); } else { LL ans = 0; if(l == r){ printf("%I64d\n",rk - lk + 1); continue; } if(rk > ans) ans = rk; if(tmp-lk+1 > ans) ans = tmp-lk+1; if(r - l > 1){ res = 0; query(1,l+1,r-1); if(res > ans) ans = res; } printf("%I64d\n",ans); } //output(1); } } 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
- 线段树?线段树!
- 线段树?线段树!
- 线段_线段树
- 线段_线段树
- 线段树
- 线段树
- Thrift 操作 Hbase
- libgdx demo
- DedeCMS 友情链接按分类网站类型调用的方法
- TAR命令的基本使用方法详解
- unity3d math 常用的数学
- hdu4973(线段树)
- SpringMVC一次请求多次进入Control的原因
- poj 2983 差分约束
- Techniques for preventing overfitting in training Deep Neural Networks
- 用curl模拟http请求获取网页
- 文件操作一些总结
- IP(Internet Protocal) 地址 说明
- c++Primer学习笔记之一:程序的编译与执行
- STOMP协议说明书-1.2版