Hdu4417线段树求区间统计+离线处理 线段树 树状数组
2012-09-24 20:35
537 查看
题意:给定一段区间每个点有个高度。在m次询问中每次给出左右端点和可以到达的高度,统计有多少个是小于到达高度
线段树
树状数组
线段树
#include <iostream> #include <algorithm> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 #define maxn 100001 #define MAXN 100001 int MAX[maxn<<2]; int scan() { int res = 0, ch, flag = 0; if((ch = getchar()) == '-') //判断正负 flag = 1; else if(ch >= '0' && ch <= '9') //得到完整的数 res = ch - '0'; while((ch = getchar()) >= '0' && ch <= '9' ) res = res * 10 + ch - '0'; return flag ? -res : res; } struct Node { int s,t; int h; int index; }node[MAXN]; int answer[MAXN]; struct SS { int index; int v; }nn[MAXN]; void PushUP(int rt) { MAX[rt] = MAX[rt<<1] + MAX[rt<<1|1]; } void build(int l,int r,int rt) { if (l == r) { //scanf("%d",&MAX[rt][0]); MAX[rt]=0; return ; } int m = (l + r) >> 1; build(lson); build(rson); PushUP(rt); } void update(int p,int add,int l,int r,int rt) { if (l == r) { MAX[rt] += add; return ; } int m = (l + r) >> 1; if (p <= m) update(p , add , lson); else update(p , add , rson); PushUP(rt); } int query(int L,int R,int l,int r,int rt) { if (L <= l && r <= R) { return MAX[rt]; } int m = (l + r) >> 1; int ret = 0; //递归调用每回求最值 if (L <= m) ret += query(L , R , lson); if (R > m) ret += query(L , R , rson); return ret; } bool cmp(SS a,SS b) { return a.v<b.v; } bool cmp2(Node a,Node b) { return a.h<b.h; } int main() { int T; int m; int n; int iCase=0; T=scan(); while(T--) { iCase++; n=scan(); m=scan(); //scanf("%d%d",&n,&m); build(1,n,1); for(int i=1;i<=n;i++) { nn[i].v=scan(); //scanf("%d",&nn[i].v); nn[i].index=i; } for(int i=0;i<m;i++) { node[i].s=scan(); node[i].t=scan(); node[i].h=scan(); //scanf("%d%d%d",&node[i].s,&node[i].t,&node[i].h); node[i].s++; node[i].t++; node[i].index=i; } sort(node,node+m,cmp2); sort(nn+1,nn+1+n,cmp); int i,j; i=1; j=0; while(j<m) { while(i<=n) { if(nn[i].v>node[j].h)break; update(nn[i].index,1,1,n,1); i++; } while(j<m) { if(i<=n&&node[j].h>=nn[i].v)break; answer[node[j].index]=query(node[j].s,node[j].t,1,n,1); j++; } } printf("Case %d:\n",iCase); for(int i=0;i<m;i++) printf("%d\n",answer[i]); } return 0; }
树状数组
#include<stdio.h> #include<algorithm> #include<string.h> using namespace std; const int MAXN=100010; int c[MAXN]; int n; int lowbit(int x) { return x&(-x); } void plus(int i,int val) { while(i<=n) { c[i]+=val; i+=lowbit(i); } } int sum(int i) { int s=0; while(i>0) { s+=c[i]; i-=lowbit(i); } return s; } struct Node { int s,t; int h; int index; }node[MAXN]; int answer[MAXN]; struct SS { int index; int v; }nn[MAXN]; bool cmp(SS a,SS b) { return a.v<b.v; } bool cmp2(Node a,Node b) { return a.h<b.h; } int input() { int ret=0; char ch; ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9') { ret*=10; ret+=ch-'0'; ch=getchar(); } return ret; } int main() { int T; int m; int iCase=0; scanf("%d",&T); //T=input(); while(T--) { iCase++; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&nn[i].v); //nn[i].v=input(); nn[i].index=i; } for(int i=0;i<m;i++) { scanf("%d%d%d",&node[i].s,&node[i].t,&node[i].h); //node[i].s=input(); //node[i].t=input(); //node[i].h=input(); node[i].s++; node[i].t++; node[i].index=i; //从1开始 所以全部起点终点++ } memset(c,0,sizeof(c)); sort(node,node+m,cmp2); sort(nn+1,nn+1+n,cmp); int i,j; i=1; j=0; while(j<m) { //因为已经排序所以可以直接统计 while(i<=n) { if(nn[i].v>node[j].h)break; plus(nn[i].index,1); i++; } while(j<m) { if(i<=n&&node[j].h>=nn[i].v)break; answer[node[j].index]=sum(node[j].t)-sum(node[j].s-1); j++; /*因为前一次询问(while(i<=n))已经找到满足当前询问满足的最大高度位置为i 下一次询问的H比当前节点的i的值要还要高说明需要找节点i(当前满足条件节点) 之后是否有满足条件的,这样省去了标记每个节点是否需要访问 */ } } printf("Case %d:\n",iCase); for(int i=0;i<m;i++) printf("%d\n",answer[i]); } return 0; }
相关文章推荐
- hdu 5381 The sum of gcd (线段树x树状数组x区间和维护进阶x离线处理)
- [hdu3333 Turing Tree] 线段树离线 处理区间不同数
- hdu4348 - To the moon 可持久化线段树 区间修改 离线处理
- hdu4777 求区间内与其它数均互质的数的个数(树状数组+离线处理)
- CodeForces 1209 B. Jury Size 树状数组处理区间统计问题
- 线段树离线处理(区间内不同的数的个数)hdu3333
- [CF#365 (Div. 2) Mishka and Interesting sum] 线段树离线处理区间不同数
- BZOJ 3110 [Zjoi2013]K大数查询 (整体二分 + 树状数组或线段树处理区间合值)
- SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)
- BZOJ-1901 Zju2112 Dynamic Rankings 函数式线段树 套 树状数组+离线处理
- hdu4417:线段树单点更新区间求和,离线 Super Mario
- hdu 3333 Turing Tree(线段树求区间内不同值之和+离线处理)
- BZOJ-1901 Zju2112 Dynamic Rankings 函数式线段树 套 树状数组+离线处理
- UPC 2224 Boring Counting (离线线段树,统计区间[l,r]之间大小在[A,B]中的数的个数)
- hdu4630 线段树||树状数组离线处理
- 线段树离线处理(区间内出现k次的数有多少个)Codeforces Round #136 (Div. 2)
- 离线处理(线段树|树状数组)| 莫对算法 —— HDU 4638 Group
- 离线记录+树状数组(hdu 5869 统计任意区间的不同gcd值)
- POJ 2887 Big String(线段树 离线处理)
- POJ 1990 MooFest(树状数组+离线处理)