hdu 4027 - 线段树 -4

来源:互联网 发布:网络图制作软件 编辑:程序博客网 时间:2024/05/17 00:12

1007   The 36th ACM/ICPC Asia Regional Shanghai Site —— Online Contest   2011ACM上海站网赛
  Can you answer these queries?
http://acm.hdu.edu.cn/showproblem.php?pid=4027
题意:给定100000个数,两种操作,0 i j表示将i j这段的数字都开根号(向下取整),1 i j表示查询i j之间的所有值的和。。。(所有的和都不超过64位)..

分析:此题的关键是要理解对任何64位以内的值,开根号最多不会超过7次,所以用线段树做,更新到叶子节点的次数最多7次,所以,每次查询如果开根号的次数很多了就直接返回,否则继续往下更新到叶子节点。。。记录几个值cnt表示当前整段更新的次数,add表示向下更新的lazy, sum[]表示该段所有值开0--max次根号的值的和。。。

此题有点类似hdu3954的方法,http://blog.csdn.net/ggggiqnypgjg/article/details/6703082  
代码:

#include <stdio.h>#include <string.h>#include <algorithm>#include <cmath>#include <iostream>using namespace std;const int N=100010;int n, m;struct node{int l, r, mid;int cnt, add;__int64 sum[8];} a[N*4];__int64 b[N], mx;int mxk;void build(int l, int r, int p){a[p].l = l;a[p].r = r;a[p].mid = (l+r)>>1;a[p].cnt = a[p].add = 0;int i;if(l==r){a[p].sum[0] = b[l];if(b[l]==0){for(i=1; i<=mxk; i++)a[p].sum[i] = 0;return ;}for(i=1; a[p].sum[i-1]>1; i++)a[p].sum[i] = sqrt((double)a[p].sum[i-1]);for( ;i<=mxk; i++)a[p].sum[i] = 1;return;}build(l, a[p].mid, p*2);build(a[p].mid+1, r, p*2+1);for(i=0; i<=mxk; i++)a[p].sum[i] = a[p*2].sum[i]+a[p*2+1].sum[i];}inline void down(int p){if(a[p].add!=0){a[p*2].cnt += a[p].add;a[p*2].add += a[p].add;a[p*2+1].cnt += a[p].add;a[p*2+1].add += a[p].add;a[p].add = 0;}}void update(int l, int r, int p){if(a[p].l==l && a[p].r==r){a[p].cnt += 1;a[p].add += 1;return;}down(p);if(r<=a[p].mid)update(l, r, p*2);else if(l>a[p].mid)update(l, r, p*2+1);else{update(l, a[p].mid, p*2);update(a[p].mid+1, r, p*2+1);}}__int64 query(int l, int r, int p){if(a[p].l==l && a[p].r==r){if(a[p].cnt>mxk)a[p].cnt = mxk;if(a[p].cnt==mxk || a[p].l==a[p].r)return a[p].sum[a[p].cnt];down(p);return query(l, a[p].mid, p*2)+query(a[p].mid+1, r, p*2+1);}down(p);if(r<=a[p].mid)return query(l, r, p*2);else if(l>a[p].mid)return query(l, r, p*2+1);elsereturn query(l, a[p].mid, p*2)+query(a[p].mid+1, r, p*2+1);}int main(){int i, cas1, op, x, y;cas1=1;while(scanf("%d", &n)!=EOF){mx = 0;for(i=1; i<=n; i++){scanf("%I64d", &b[i]);if(b[i]>mx)mx = b[i];}for(i=1; mx>1; i++, mx=sqrt((double)mx));mxk = i;build(1, n, 1);scanf("%d", &m);printf("Case #%d:\n", cas1++);while(m--){scanf("%d%d%d", &op, &x, &y);if(x>y)swap(x, y);if(op==0)update(x, y, 1);elseprintf("%I64d\n", query(x, y, 1));}printf("\n");}return 0;}


比赛代码:
#include <stdio.h>#include <string.h>#include <algorithm>#include <cmath>#include <iostream>using namespace std;const int N=200010;int n, m;struct node{int l, r, mid;int cnt, add;int fl, fr;__int64 sum[15];} a[N*4];__int64 b[N], mx;int mxk;void build(int l, int r, int p){a[p].l = l;a[p].r = r;a[p].mid = (l+r)>>1;a[p].cnt = a[p].add = 0;a[p].fl = a[p].fr = 0;int i;if(l==r){a[p].sum[0] = b[l];if(b[l]==0){for(i=1; i<=mxk; i++)a[p].sum[i] = 0;return ;}for(i=1; a[p].sum[i-1]>1; i++)a[p].sum[i] = (__int64)sqrt((double)a[p].sum[i-1]);for( ;i<=mxk; i++)a[p].sum[i] = 1;return;}build(l, a[p].mid, p*2);build(a[p].mid+1, r, p*2+1);for(i=0; i<=mxk; i++)a[p].sum[i] = a[p*2].sum[i]+a[p*2+1].sum[i];}inline void down(int p){if(a[p].add!=0){a[p*2].cnt += a[p].add;a[p*2].add += a[p].add;a[p*2+1].cnt += a[p].add;a[p*2+1].add += a[p].add;a[p].add = 0;}}void update(int l, int r, int p){if(a[p].l==l && a[p].r==r){a[p].cnt += 1;a[p].add += 1;return;}down(p);if(r<=a[p].mid){update(l, r, p*2);a[p].fl = 1;}else if(l>a[p].mid){update(l, r, p*2+1);a[p].fr = 1;}else{a[p].fl = 1;a[p].fr = 1;update(l, a[p].mid, p*2);update(a[p].mid+1, r, p*2+1);}}__int64 query(int l, int r, int p){if(a[p].l==l && a[p].r==r){if(a[p].cnt>mxk)a[p].cnt = mxk;if(a[p].cnt==mxk)return a[p].sum[a[p].cnt];//if( (a[p].fl || a[p].fr)==0)  //下面的cnt都一样。。//return a[p].sum[a[p].cnt];if(a[p].l==a[p].r)return a[p].sum[a[p].cnt];down(p);return query(l, a[p].mid, p*2)+query(a[p].mid+1, r, p*2+1);}down(p);if(r<=a[p].mid)return query(l, r, p*2);else if(l>a[p].mid)return query(l, r, p*2+1);else{return query(l, a[p].mid, p*2)+query(a[p].mid+1, r, p*2+1);}}int main(){//freopen("D.in", "r", stdin);//freopen("D.out", "w", stdout);int i, cas1, op, x, y;cas1=1;while(scanf("%d", &n)!=EOF){mx = 0;for(i=1; i<=n; i++){scanf("%I64d", &b[i]);if(b[i]>mx)mx = b[i];}for(i=1; mx>1; i++, mx=(__int64)sqrt((double)mx));mxk = i;mxk += 3;build(1, n, 1);scanf("%d", &m);printf("Case #%d:\n", cas1++);while(m--){scanf("%d%d%d", &op, &x, &y);if(x>y)swap(x, y);if(op==0)update(x, y, 1);elseprintf("%I64d\n", query(x, y, 1));}printf("\n");}return 0;}