Hdu4417线段树求区间统计+离线处理 线段树 树状数组

来源:互联网 发布:mysql登录失败 编辑:程序博客网 时间:2024/04/30 19:36

题意:给定一段区间每个点有个高度。在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  100001int 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;}