线段树——单点更新(二)
2012-07-22 10:35
134 查看
HDU 4217 Data Structure?
http://acm.hdu.edu.cn/showproblem.php?pid=4217
CZ做的一道题目,我帮忙看了看。
题意:给定N个数(1---N),K个操作,然后给K数,i1,i2,i3.......ik 每次取走当前状态下等的第i个数(从小到大的),问取走的数的和。
给的那个的n为262144可以断定肯定是O(n*log(n))级的算法,所以选定线段树。
叶子节点赋值为1,这些节点存储的就是数的个数,在添加一个val数组记录是哪个数。每次更新将节点a[rt]变成0,找出对应的val[rt]即可。
这里坑爹的地方时sum求和时,要用—int64.wa了很多次才发现。
View Code
1006 hdu 4325 http://acm.hdu.edu.cn/showproblem.php?pid=4325
/article/7104919.html
pku Sliding Window http://poj.org/problem?id=2823
题解:/article/7104951.html
http://acm.hdu.edu.cn/showproblem.php?pid=4217
CZ做的一道题目,我帮忙看了看。
题意:给定N个数(1---N),K个操作,然后给K数,i1,i2,i3.......ik 每次取走当前状态下等的第i个数(从小到大的),问取走的数的和。
给的那个的n为262144可以断定肯定是O(n*log(n))级的算法,所以选定线段树。
叶子节点赋值为1,这些节点存储的就是数的个数,在添加一个val数组记录是哪个数。每次更新将节点a[rt]变成0,找出对应的val[rt]即可。
这里坑爹的地方时sum求和时,要用—int64.wa了很多次才发现。
View Code
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> #include <string> #define CL(a,num) memset((a),(num),sizeof(a)) #define iabs(x) ((x) > 0 ? (x) : -(x)) #define Min(a,b) (a) > (b)? (b):(a) #define Max(a,b) (a) > (b)? (a):(b) #define ll __int64 #define inf 0x7f7f7f7f #define MOD 1000000007ll #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define test puts("<------------------->") #define maxn 100010 #define N 1000005 #define M 200007 using namespace std; int val[maxn<<2]; int pos[maxn]; void pushup(int rt) { val[rt] = val[rt<<1] + val[rt<<1|1]; } void build(int l,int r,int rt) { if (l == r) { val[rt] = 1; return ; } int m = (l + r)>>1; build(lc); build(rc); pushup(rt); } void update(int pos,int l,int r,int rt) { if (l == r) { val[rt] = 0; return ; } int m = (l + r)>>1; if (pos <= m) update(pos,lc); else update(pos,rc); pushup(rt); } int query(int L,int R,int l,int r,int rt) { if (l >= L && r <= R) return val[rt]; int res = 0; int m = (l + r)>>1; if (L <= m) res += query(L,R,lc); if (R > m) res += query(L,R,rc); return res; } int getpos(int s,int l,int r,int rt) { if (l == r) return l; int m = (l + r)>>1; if (s <= val[rt<<1]) return getpos(s,lc); else { s -= val[rt<<1]; return getpos(s,rc); } } int main() { //freopen("din.txt","r",stdin); int n,i,a; while (~scanf("%d",&n)) { if (!n) break; for (i = 1; i <= n; ++i) { scanf("%d",&a); pos[a] = i;//标记第a个被扔出去的编号 } build(1,n,1); int curpos = 1;//当前在手中的点的标号 ll ans = 0; for (i = 1; i <= n; ++i) { int tmp = 0; if (curpos == pos[i]) ans += 1;//只剩一个点了 else if (curpos < pos[i])//1 2 3 4 5; 3要被删除 { tmp = query(curpos + 1,pos[i],1,n,1); ans += (min(tmp,n - i + 1 - tmp) + 1);//n - i + 1 - tmp就是顺时针的个数了,这里比赛时写麻烦了 } else//同理 { tmp = query(pos[i],curpos - 1,1,n,1); ans += (min(tmp,n - i + 1 - tmp) + 1); } //printf(">>%d %d %d %d\n",tmp,n - i + 1 - tmp,Min(tmp,n - i + 1 - tmp),(Min(tmp,n - i + 1 - tmp) + 1));//这里发现了用宏定义的Min不行出错 update(pos[i],1,n,1); int s = query(1,pos[i],1,n,1); if (s < n - i)//如果pos[i]后面还有未被删除的点 curpos = getpos(s + 1,1,n,1); else//如果没有就找第一个未被删除的点 curpos = getpos(1,1,n,1); } printf("%I64d\n",ans); } return 0; }
1006 hdu 4325 http://acm.hdu.edu.cn/showproblem.php?pid=4325
/article/7104919.html
pku Sliding Window http://poj.org/problem?id=2823
题解:/article/7104951.html
相关文章推荐
- 线段树区间最大值查询,单点更新,建立模板
- buy tickrt(线段树)单点更新应用变形
- hdu4046 不错的线段树单点更新
- 数据结构之线段树 单点更新
- ZOJ 5638——Prime Query——————【线段树区间更新,区间查询,单点更新】
- Codeforces Round #343 (Div. 2) B. Far Relative’s Problem (线段树+区间更新+单点查询)
- 线段树单点更新 HDU 2795
- hdu 1166 线段树单点更新
- HDU 1394 Minimum Inversion Number (线段树 单点更新 求逆序数)
- 线段树简单入门模板--单点更新
- 线段树·HDU1166 敌兵布阵·单点更新区间求和
- hdu 1166 敌兵布阵(线段树单点更新(a位置的值+/-b)+区间求和)
- hdu 5475 An easy problem(线段树单点更新)
- hdu - 1754 - I Hate It(线段树(单点更新))
- hdu 1754 线段树区间最大值 单点更新
- POJ 2352_Stars && POJ-2481 Cows (线段树单点更新+树状数组)
- HDU5861 (线段树区间更新+单点查询)
- nyoj116士兵杀敌(二)线段树单点更新
- poj 2886 Who Gets the Most Candies?(线段树单点更新模拟约瑟夫环)
- HDU 2795 Billboard 线段树单点更新