2019南京ICPC网络赛A题

二维偏序,利用二维前缀和的思想,一个矩阵(x1,y1,x2,y2)可以由(0,0,x2,y2)+(0,0,x1-1,x2-1)-(0,0,x1-1,y2)-(0,0,x2,y1-1)得出,所以按x轴排序,用树状数组记录y轴的(0,y]的值,然后就ok了。
此题有一个nc坑点,就是他让你计算的一个点的权值不是这个值在螺旋矩阵中的值,而是螺旋矩阵的值的每位数的和,列如5*5的螺旋矩阵在(3,3)为25,但是其实这个点的权值是7(2+5),而且样例因为都是个位数所以按权值和算完全符合!
螺旋矩阵给出坐标求出相应值的函数是copy的网上的模板。

#include
#include
#include
#include
using namespace std;
const int MAX_N=1e5+1000;
int n;
struct skt{
    int x,y,sum;
}a[MAX_N];
struct kt{
    int x,y,num;
    int sum;
}b[4*MAX_N];
struct ssg{
    int x1,y1,x2,y2;
    int a,b,c,d;
}que[MAX_N];
bool cmp(skt a,skt b){
    return a.x<b.x;
}
bool cmpp(kt a,kt b){
    return a.x<b.x;
}
int sum[1010000];
void add(int p,long long x){
    while(p<=n){
        sum[p]+=x;
        p+=p&-p;
    }
}
int ask(int p){
    int ans=0;
    while(p){
        ans+=sum[p];
        p-=p&-p;
    }
    return ans;
}
long long asking(long long n,long long a,long long b){
 long long q=min(min(a,b),min(n-a+1,n-b+1));
 long long ans=0;
 if(a<=b){
  q--;
  ans=4*(n-q)*q+a+b-2*(q+1)+1;
    }
    else
  ans=4*(n-q)*q-a-b+2*q+1;
 return ans;
}
int work(long long x){
    int ans=0;
    while(x){
        ans+=x%10;
        x=x/10;
    }
    return ans;
}
int main(void){
    int T,m,q,i;
    int x1,x2,y1,y2;
    cin>>T;
    while(T--){
        scanf("%d%d%d",&n,&m,&q);
        for(i=0;i<=n;i++)
            sum[i]=0;
        for(i=0;i<m;i++){
            scanf("%d%d",&a[i].x,&a[i].y);
            long long qx=n-a[i].x+1,qy=n-a[i].y+1;
            long long N=n;
            a[i].sum=work(asking(N,qx,qy));
            //cout<
            //cout<
        }
        sort(a,a+m,cmp);
        for(i=0;i<q;i++){
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            que[i].x1=x1;que[i].y1=y1;que[i].x2=x2;que[i].y2=y2;
            b[4*i].x=x1-1;b[4*i].y=y1-1;b[4*i].num=4*i;
            b[4*i+1].x=x1-1;b[4*i+1].y=y2;b[4*i+1].num=4*i+1;
            b[4*i+2].x=x2;b[4*i+2].y=y1-1;b[4*i+2].num=4*i+2;
            b[4*i+3].x=x2;b[4*i+3].y=y2;b[4*i+3].num=4*i+3;
        }
        sort(b,b+4*q,cmpp);
        int cnta=0,cntb=0;
        a[m].x=1e9;b[4*q].x=1e9;
        while(cnta<m||cntb<4*q){
            //cout<
            if(a[cnta].x<=b[cntb].x){
                add(a[cnta].y,a[cnta].sum);
                cnta++;
            }
            else{
                b[cntb].sum=ask(b[cntb].y);
                cntb++;
            }
        }
        //cout<<"asdfa\n";
        for(i=0;i<4*q;i++){
            if(b[i].num%4==0)
            que[b[i].num/4].a=b[i].sum;
            else if(b[i].num%4==1)
            que[b[i].num/4].b=b[i].sum;
            else if(b[i].num%4==2)
            que[b[i].num/4].c=b[i].sum;
            else
            que[b[i].num/4].d=b[i].sum;
        }
        for(i=0;i<q;i++){
            int ans=que[i].a-que[i].b-que[i].c+que[i].d;
            //cout<
            printf("%d\n",ans);
        }
    }
    return 0;
}

你可能感兴趣的:(分治)