• A.The beautiful values of the palace 南京网络赛


     A对于知道了解主席树性质的人来说,的确算是一个模板题目

    题目在于给一个螺旋矩阵,以及一些权值,问在二维区间内权值和是多少?

    对于螺旋矩阵权值来说,计算每个点的值,只需要O1计算即可。我们可以通过计算内部圈数得到计算外围的权值,再加当前圈数即可

    而对于二维的区间和,我们知道其实主席树已经是二维的了,因为我们在每个节点都新开一棵线段树。并且主席树是动态开点的,这样就比较简单了。

    我们考虑把所有加入有权值的点进行排序,那么区间和,转换为了二维偏序前缀和。

    第一维是x,也就root[ i ]纬度,第二维是y,也就是主席树内部维护的前缀和。

    我们通过lower_bound+upper_bound查询x坐标对应区间内x来说,它所在的主席树的区间的版本

    然后同理我们可以查lower_bound+upper_bound查询y坐标对于区间内y来说,它在主席树上的区间和。

    这样我们就能很容易的计算出答案。

    注意由于我们查询区间坐标的时候

     lx=lower_bound(vx.begin(),vx.end(),lx)-vx.begin()+1

    rx=lower_bound(vx.begin(),vx.end(),rx)-vx.begin()

    因为我们查询的是,第一个大于等于lx的,以及第一个小于等于rx,

     如果这个值没有的话,rx<lx,我们必须特判情况。否则线段树会超时。

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<vector>
    #define LL long long
    using namespace std;
    const int maxx = 1e5+10;
    struct node{
       int l,r;
       LL w;
    }tree[maxx*40];
    int root[maxx];
    struct Node{
       int x,y;
       LL w;
       bool operator < (const Node & s)const{
         return x<s.x;
       }
    }point[maxx];
    vector<int>vx;
    vector<int>vy;
    LL n;
    int cnt;
    LL get_val(LL x,LL y){
        LL k=min(x,min(n-x+1,min(y,n-y+1)));
        LL minn=k;
        k--;
        LL in=n-2*k;
        LL out=n*n-in*in;
        if (x==n-minn+1){
            return out+n-k-y+1;
        }else if (y==minn){
            return out+in+n-k-x;
        }else if (x==minn){
            return out+in*2-2+y-k;
        }else {
            return out+in*3-3+x-k;
        }
    }
    ////主席树维护y偏序的区间和
    void inserts(int l,int r,int pre,int &now,int pos,LL w){
       now=++cnt;
       tree[now]=tree[pre];
       tree[now].w+=w;
       if(l==r){
         return ;
       }
       int mid=(l+r)>>1;
       if(pos<=mid)inserts(l,mid,tree[pre].l,tree[now].l,pos,w);
       else inserts(mid+1,r,tree[pre].r,tree[now].r,pos,w);
    }
    LL query(int L,int R,int l,int r,int ql,int qr){
        //区间查询
        if(ql<=l && r<=qr){
           return tree[R].w-tree[L].w;
        }
        int mid=(l+r)>>1;
        LL ans=0;
        if (qr<=mid){
            return query(tree[L].l,tree[R].l,l,mid,ql,qr);
        }else if (ql>mid){
             return query(tree[L].r,tree[R].r,mid+1,r,ql,qr);
        }else {
             return query(tree[L].l,tree[R].l,l,mid,ql,qr)+query(tree[L].r,tree[R].r,mid+1,r,ql,qr);
        }
    }
    LL cal(LL x) {
        LL sum = 0;
        while (x)
            sum += x % 10, x /= 10;
        return sum;
    }
    int main(){
      int T;
      int m,p;
      scanf("%d",&T);
      while(T--){
         cnt=0;
         memset(root,0,sizeof(root));
         memset(tree,0,sizeof(tree));
         scanf("%lld%d%d",&n,&m,&p);
         vx.clear();
         vy.clear();
         for(int i=1;i<=m;i++){
            scanf("%d%d",&point[i].x,&point[i].y);
            point[i].w=cal(get_val(point[i].x,point[i].y));
            vx.push_back(point[i].x);
            vy.push_back(point[i].y);
         }
         sort(point+1,point+1+m);
         sort(vx.begin(),vx.end());
         sort(vy.begin(),vy.end());
         vy.erase(unique(vy.begin(),vy.end()),vy.end());
         int sz=vy.size();
         for (int i=1;i<=m;i++){
           int posy=lower_bound(vy.begin(),vy.end(),point[i].y)-vy.begin()+1;
            inserts(1,sz,root[i-1],root[i],posy,point[i].w);
         }
         while(p--){
          int lx,rx,ly,ry;
          scanf("%d%d%d%d",&lx,&ly,&rx,&ry);
           lx=lower_bound(vx.begin(),vx.end(),lx)-vx.begin()+1;
           rx=upper_bound(vx.begin(),vx.end(),rx)-vx.begin();
           ly=lower_bound(vy.begin(),vy.end(),ly)-vy.begin()+1;
           ry=upper_bound(vy.begin(),vy.end(),ry)-vy.begin();
           if (lx>rx || ly>ry){
              printf("0
    ");
              continue;
           }
           printf("%lld
    ",query(root[lx-1],root[rx],1,sz,ly,ry));
         }
    
      }
      return 0;
    }
    /*
    
    
    */
    有不懂欢迎咨询 QQ:1326487164(添加时记得备注)
  • 相关阅读:
    区间DP中的环形DP
    hdu 5251 包围点集最小矩形 ***
    hdu 4858 水题
    hdu 3530 单调队列 **
    hdu 3338 最大流 ****
    hdu 2732 最大流 **
    hdu 5233 离散化 **
    hdu 3555 数位dp *
    zoj 3469 区间dp **
    2015 安徽程序设计省赛总结
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11450672.html
Copyright © 2020-2023  润新知