2019南京网络赛-A-The beautiful values of the palace(树状数组 二维偏序)

题目链接

题意

一个螺旋的矩阵,大小为n*n,n一定为奇数。有m个位置有值,值就是螺旋矩阵上的值,其他没有列举的位置都为0. 给了x1,y1,x2,y2,求矩形区域(x1,y1)(x2,y2)内所有数的综合。

思路

求矩形区域,可以转化为求四个前缀和。但是1e6限制了不能用二维树状数组,所以求前缀和的时候按照Y从小到大的顺序,将二维转化为一维。

会爆int,用ll存

参考


#include <bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

ll getNum(ll x,ll y,ll n) //得到螺旋矩阵的数
{
    x = x-n/2-1;
    y = y-n/2-1;
    ll t = max(abs(x),abs(y));//第几个螺旋
    ll ans;
    if(x>=y) ans = n*n-4*t*t-2*t-x-y;
    else ans = n*n-4*t*t+2*t+x+y;
    return ans;
}

ll getDigit(ll x) //求数的各位数字和
{
    ll ans = 0;
    while(x){
        ans += x%10;
        x /=10;
    }
    return ans;
}
const int N = 1e6+10;
ll c[N];ll ans[N]; //c是树状数组,ans是第i次访问的答案
ll n,m,p,tot;

ll lowbit(ll i){ return i & -i; }
void update(ll i,ll v)
{
    while(i<=n){
        c[i] += v;
        i += lowbit(i);
    }
}
ll sum(ll i)
{
    ll ret = 0;
    while(i>0){
        ret += c[i];
        i -= lowbit(i);
    }
    return ret;
}

struct node1 // 存有值的点
{
    ll x,y,w;
}point[N];
bool cmp1(node1 a,node1 b){return a.y<b.y;}


struct node2 //存访问的前缀和
{
    ll x,y,id,flag;
    node2(){}
    node2(ll _x,ll _y,ll _id,ll _flag):
        x(_x),y(_y),id(_id),flag(_flag){}
}q[N*4];
bool cmp2(node2 a,node2 b){return a.y<b.y;}


void solve()
{
    memset(c,0,sizeof(c));
    memset(ans,0,sizeof(ans));
    sort(point+1,point+1+m,cmp1);
    sort(q+1,q+1+tot,cmp2);
    
    int k = 1;
    for(int i=1;i<=tot;i++){
        while(k<=m && q[i].y>=point[k].y){//有值的点没有添加完 && 访问前缀和的y值大于等于添加点的y值
            if(point[k].x!=0) update(point[k].x,point[k].w);//添加点,一直到树状数组c存的是小于等于y的前缀和
            k++;
        }
        if(q[i].x!=0) {
            ans[q[i].id] += sum(q[i].x)*q[i].flag;
        }
    }
}

int main()
{
    int T; scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&p);
        for(int i=1;i<=m;i++){
            int x,y;scanf("%d%d",&x,&y);
            point[i].x = x; point[i].y = y; point[i].w = getDigit(getNum(x,y,n));
        }

        tot = 0;
        for(int i=1;i<=p;i++){
            int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            q[++tot] = node2(x2,y2,i,1);
            q[++tot] = node2(x1-1,y1-1,i,1);
            q[++tot] = node2(x1-1,y2,i,-1);
            q[++tot] = node2(x2,y1-1,i,-1);
        }
        solve();
        for(int i=1;i<=p;i++){
            printf("%lld\n",ans[i]);
        }
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章