• 树状数组总结篇


    (本来对于树状数组没啥感觉的....毕竟潜意识的认为只要树状数组的能够解决的问题我都可以用线段树解决,但是对于一些玄学题目可能会被卡掉T 因为在树状数组能适用的题,他在空间和时间都优于线段树,所以学好树状数组也是很重要的,具体的实现过程百度.....实质上只是二进制的运用 熟练运用二进制就能解决相关问题;

    传送门http://poj.org/problem?id=3067

    题意:在日本的东海岸和西海岸修交通线,问这些交通线有多少交叉点;

    解法:按照x坐标升序,相同的情况下y升序排序,然后查询在之前有多少满足条件的即可

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #define N 1005
    #define ll long long
    using namespace std;
    typedef struct node{
        int x;int y;
        friend bool operator <(node a,node b){
            if(a.x==b.x)  return a.y<b.y;
            else return a.x<b.x;
        }
    }node;
    node a[N*N];
    ll d[N];
    int get_id(int x){
        return x&(-x);
    }
    void update(int x){
        while(x<=N){
            d[x]++;x+=get_id(x);
        }
    }
    ll Sum(int x){
      ll ans=0;
      while(x>0){
        ans+=d[x];x-=get_id(x);
      }
      return ans;
    }
    int main(){
        int T;scanf("%d",&T);
        int n,m,k;int Case=0;
        while(T--){
            scanf("%d%d%d",&n,&m,&k);
            int aa,bb;
            memset(d,0,sizeof(d));
            for(int i=1;i<=k;i++){
                scanf("%d%d",&a[i].x,&a[i].y);
            }
            sort(a+1,a+k+1);
            update(a[1].y);
            ll sum=0;
           for(int i=2;i<=k;i++){
             sum+=(i-1-Sum(a[i].y));
             update(a[i].y);
           }
           printf("Test case %d: ",++Case);
           printf("%lld
    ",sum);
        }
        return 0;
    }

    传送门 http://poj.org/problem?id=3321

    题意:给你一颗苹果树,每个节点初始都有一个苹果,执行一些操作(有苹果的直接拿掉 没有的直接补上去一个苹果),然后查询这个节点的子树上有多少个苹果;

    解法:第一反应树剖+树状数组查询区间和(似乎有更简单的树状数组 并不会2333333)

    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #define N 100005
    using namespace std;
    int pos;int son[N];int deep[N];int a[N];
    int first[N*2];int Next[N*2];int vi[N*2];
    void intx(){
        pos=0;
        deep[0]=0;
        for(int i=1;i<N;i++)   first[i]=-1;
        for(int i=1;i<N;i++) son[i]=-1;
    }
    int fa[N];int num[N];
    void dfs1(int v,int pre){
        fa[v]=pre;num[v]=1;deep[v]=deep[pre]+1;
        for(int i=first[v];i!=-1;i=Next[i]){
            if(vi[i]!=pre){
                dfs1(vi[i],v);
                num[v]+=num[vi[i]];
                if(son[v]==-1||num[son[v]]<num[vi[i]]){
                    son[v]=vi[i];
                }
            }
        }
    }
    int p[N];int tp[N];int fp[N];
    void dfs2(int v,int td){
        p[v]=++pos;fp[p[v]]=v;tp[v]=td;
        if(son[v]!=-1) dfs2(son[v],td);
        for(int i=first[v];i!=-1;i=Next[i]){
            if(vi[i]!=fa[v]&&vi[i]!=son[v]) dfs2(vi[i],vi[i]);
        }
    }
    int d[N];
    int get_id(int x){
        return x&(-x);
    }
    int n;
    void get_d(int n){
        for(int i=1;i<=n;i++){
            int j=i;
            while(j<=n){
                d[j]+=a[i];j+=get_id(j);
            }
        }
    }
    void update(int x,int t){
        while(x<=n){
            d[x]+=t;x+=get_id(x);
        }
    }
    int Sum(int x){
        int ans=0;
        while(x>0){
            ans+=d[x];x-=get_id(x);
        }
        return ans;
    }
    int main(){
        while(scanf("%d",&n)==1){
                int aa,bb;
                intx();
            for(int i=1;i<=(n-1)*2;i++){
                scanf("%d%d",&aa,&bb);
                Next[i]=first[aa];
                first[aa]=i;
                vi[i]=bb;
                i++;
                Next[i]=first[bb];
                first[bb]=i;
                vi[i]=aa;
               // vec[aa].push_back(bb);vec[bb].push_back(aa);
            }
            dfs1(1,0);
            dfs2(1,1);
            memset(a,0,sizeof(a));
            for(int i=1;i<=n;i++) a[i]=1;
            memset(d,0,sizeof(d));
            get_d(n);
            int q;scanf("%d",&q);char s[5];
            for(int i=1;i<=q;i++){
                scanf("%s",s);
                if(s[0]=='Q'){
                    scanf("%d",&aa);
                    int t1=p[aa];int t2=p[aa]+num[aa]-1;
                    printf("%d
    ",Sum(t2)-Sum(t1-1));
                }
                else if(s[0]=='C'){
                    scanf("%d",&aa);
                    if(a[aa]==0){
                        a[aa]=1;update(p[aa],1);
                    }
                    else{
                        a[aa]=0;update(p[aa],-1);
                    }
                }
            }
           // for(int i=1;i<=n;i++) vec[i].clear();
        }
        return 0;
    }

    传送门http://poj.org/problem?id=2481

    题意:求一个区间是多少个区间真子区间(只允许一个端点相同)

    解法:按照x升序排序后,x相同时按照y的降序排序;然后查询即可(可能存在完全相等的两个区间;要注意这个下标从0开始)

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <map>
    #include <vector>
    #include <cstdio>
    #define N 100005
    using namespace std;
    typedef struct node{
        int x;int  y;int biao;
        friend bool operator<(node a,node b){
            if(a.x==b.x) return a.y>b.y;
            return  a.x<b.x;
        }
    }node;
    node a[N];
    int d[N];int vis[N];
    int get_id(int x){
        return x&(-x);
    }
    void update(int x){
        while(x<=N){
            d[x]++;x+=get_id(x);
        }
    }
    void Sum(int x,int biao){
        int ans=0;
        while(x>0){
            ans+=d[x];
            x-=get_id(x);
        }
        vis[biao]=ans;
    }
    int main(){
        int n;
        while(scanf("%d",&n)==1&&n){
            int xx,yy;node t;
            memset(vis,0,sizeof(vis));
            memset(d,0,sizeof(d));
            for(int i=1;i<=n;i++){
                scanf("%d%d",&a[i].x,&a[i].y);a[i].x++;a[i].y++;a[i].biao=i;
            }
           int u=0;
           sort(a+1,a+n+1);
           for(int i=1;i<=n;i++){
            if(i==1){
           Sum(a[i].y-1,a[i].biao);
           vis[a[i].biao]=u-vis[a[i].biao];
             }
             else{
                if(a[i].x==a[i-1].x&&a[i].y==a[i-1].y) vis[a[i].biao]=vis[a[i-1].biao];
                else{
                    Sum(a[i].y-1,a[i].biao);    vis[a[i].biao]=u-vis[a[i].biao];
                }
             }
             u++;
             update(a[i].y);
           }
           for(int i=1;i<=n;i++){
            if(i==1) printf("%d",vis[i]);
            else printf(" %d",vis[i]);
           }
           printf("
    ");
        }
        return 0;
    }

     传送门http://poj.org/problem?id=2352

    题意:给你每个星星的位置,求这个星星的坐标范围内有多少个星星(包括自己)

    题解:按照x升序x相同时升序,查找统计即可;

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #define N 32005
    #define M 15005
    using namespace std;
    typedef struct node{
        int x;int y;
        friend bool operator<(node a,node b){
            if(a.x==b.x) return a.y<b.y;
            return a.x<b.x;
        }
    }node;
    int n;
    node a[M];
    int d[N];int vis[N];
    int get_id(int x){
        return x&(-x);
    }
    void update(int x){
        while(x<=N){
            d[x]++;
            x+=get_id(x);
       }
    }
    void Sum(int x){
        int ans=0;
        while(x>0){
            ans+=d[x];
            x-=get_id(x);
        }
        vis[ans]++;
    }
    int main(){
        while(scanf("%d",&n)==1){
        int xx;int yy;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&xx,&yy);a[i].x=xx+1;a[i].y=yy+1;
          }
          memset(vis,0,sizeof(vis));
          memset(d,0,sizeof(d));
          sort(a+1,a+n+1);
          for(int i=1;i<=n;i++){
           update(a[i].y);
           Sum(a[i].y);
           }
           for(int i=1;i<=n;i++){
            printf("%d
    ",vis[i]);
          }
        }
        return 0;
    }

     最后一题:

    传送门http://poj.org/problem?id=1195

    题意:给一个正方形,初始都是0,1操作是一个点的修改,2查询左下角和右上角形成的矩阵的和

    题解:一维树状数组拓展为二维树状数组 在x y方向彼此独立

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #define ll long long
    using namespace std;
    ll d[1030][1030];
    int get_id(int x){
        return x&(-x);
    }
    void update(int x,int y,int vulue){
        for(int i=x;i<=1030;i+=get_id(i)){
            for(int j=y;j<=1030;j+=get_id(j)){
                d[i][j]+=vulue;
            }
        }
    }
    int sum(int x,int y){
        int ans=0;
        for(int i=x;i>0;i-=get_id(i)){
            for(int j=y;j>0;j-=get_id(j)){
                ans+=d[i][j];
            }
        }
        return ans;
    }
    int main(){
        int k;int n;
        while(scanf("%d %d",&k,&n)==2){
            if(k!=0) break;
            memset(d,0,sizeof(d));
            int t;
            int aa,bb,cc,x1,y1;
            while(scanf("%d",&t)==1&&t!=3){
                if(t==1){
                    scanf("%d%d%d",&aa,&bb,&cc);
                    update(aa+1,bb+1,cc);
                }
                else if(t==2){
                    scanf("%d%d%d%d",&aa,&bb,&x1,&y1);
                    aa++;bb++;x1++;y1++;
                    printf("%d
    ",sum(x1,y1)-sum(aa-1,y1)-sum(x1,bb-1)+sum(aa-1,bb-1));
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    sql server 2000 “因为选定的用户拥有对象,所以无法除去该用户。”问题(含图说明)
    关于datalength函数,解决ntext等无法比较空值的问题
    Analysis service的manager无法连接,不能连接服务器(xxxxx)注册表,或者还不是olap Administrator组成员
    数据库查询问题int型字段对应以Int型数值+','组成的nvarchar型字段
    Asp与Asp.net共用cookie
    什么是SPSS
    TransactSQL语言提供的日期和时间函数(以备后用)
    关于sql语句的执行效率测试
    sqlserver数据仓库学习第一课(含资料)
    理解collate Chinese_PRC_CI_AS NULL
  • 原文地址:https://www.cnblogs.com/wang9897/p/7624491.html
Copyright © 2020-2023  润新知