2019ICPC南京網絡賽 A.The beautiful values of the palace 離線樹狀數組或者CDQ分治或者主席樹

Here is a square matrix of n * nn∗n, each lattice has its value (nn must be odd), and the center value is n * nn∗n. Its spiral decline along the center of the square matrix (the way of spiral decline is shown in the following figure:)The grid in the lower left corner is (1,1) and the grid in the upper right corner is (n , n)

Now I can choose mm squares to build palaces, The beauty of each palace is equal to the digital sum of the value of the land which it is located. Such as (the land value is 123213123213,the beautiful values of the palace located on it is 1+2+3+2+1+3=121+2+3+2+1+3=12) (666666 -> 1818) (456456 ->1515)

Next, we ask pp times to the sum of the beautiful values of the palace in the matrix where the lower left grid(x_1,y_1x1​,y1​), the upper right square (x_2,y_2x2​,y2​).

Input

The first line has only one number TT .Representing TT-group of test data (T\le 5)(T≤5)

The next line is three number: n \ m \ pn m p

The mm lines follow, each line contains two integers the square of the palace (x, y )(x,y)

The pp lines follow, each line contains four integers : the lower left grid (x_1,y_1)(x1​,y1​) the upper right square (x_2,y_2)(x2​,y2​)

Output

Next, p_1+p_2...+p_Tp1​+p2​...+pT​ lines: Represent the answer in turn(n \le 10^6)(m , p \le 10^5)(n≤106)(m,p≤105)

樣例輸入複製

1
3 4 4
1 1
2 2
3 3
2 3
1 1 1 1
2 2 3 3
1 1 3 3
1 2 2 3

樣例輸出複製

5
18
23
17

題意:

給一個n*n的蛇形矩陣,n爲奇數。給定m個宮殿,處在每個宮殿位置(x,y)的點有一個beautiful value等於此點蛇形矩陣上數字的各位數和。p個詢問, 給出一個矩形左下角的點(x1,y1)和右上角的點(x2,y2),問被矩形覆蓋的所有宮殿的value總和是多少。

分析:

離線樹狀數組

類似於求矩陣的前綴和的思想,對於詢問左下角(x1,y1),右上角(x2,y2)

該詢問答案爲a[x2][y2]-a[x1-1][y2]-a[x2][y1-1]+a[x1-1][y1-1],我們對x座標建立樹狀數組,插入y的值,統計x值的貢獻即可,看一下代碼就明白了。即我們把詢問拆成四個前綴和,和m個點一起離線,樹狀數組更新答案即

CDQ分治

模板題

主席樹

待理解

 

樹狀數組

#include <bits/stdc++.h>
using namespace std;
const int maxm=1e6+100;
typedef long long LL;
const int N=1e6;
struct Node
{
    LL x,y;
    LL id,w,tag;
} q[maxm];
LL sum[maxm],ans[maxm];
LL n,m,Q,cnt,t;
inline int lowbit(int x)
{
    return x&(-x);
}
inline void ins(int x,LL val)
{
    for(int i=x; i<=N; i+=lowbit(i))
        sum[i]+=val;
}
inline int ask(LL x)
{
    LL res=0;
    for(int i=x; i; i-=lowbit(i))
        res+=sum[i];
    return res;
}
inline bool comp(Node p,Node q)
{
    return (p.x<q.x)||((p.x==q.x)&&(p.tag>q.tag));
}
inline LL cal(LL x,LL y)
{
    LL layer=std::min(std::min(x, y),n-std::max(x, y)+1);
    if((layer<<1)>n)
        return n*n;
    LL st=n*n-(n-(layer<<1)+2)*(n-(layer<<1)+2)+1;
    if (x>=y)
        return st+((n-layer)<<1)+2-x-y;
    return st+((n-(layer<<1)+1)<<1)+x+y-(layer<<1);
}
inline LL split(LL x)
{
    LL res=0;
    while(x)
    {
        res+=x%10;
        x/=10;
    }
    return res;
}
inline void work()
{
    scanf("%lld%lld%lld",&n,&m,&Q);
    cnt=0;
    memset(sum,0,sizeof(sum));
    LL x,y;
    for(int i=1; i<=m; i++)
    {
        scanf("%lld%lld",&x,&y);
        q[++cnt]=Node{x,y,0,split(cal(x,y)),2};
    }
    LL x1,y1,x2,y2;
    for(int i=1; i<=Q; i++)
    {
        scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
        ans[i]=0;
        q[++cnt]=Node{x2,y2,i,0,1};
        q[++cnt]=Node{x2,y1-1,i,0,-1};
        q[++cnt]=Node{x1-1,y2,i,0,-1};
        q[++cnt]=Node{x1-1,y1-1,i,0,1};
    }
    sort(q+1,q+cnt+1,comp);
    for(int i=1; i<=cnt; i++)
    {
        if(q[i].tag==2)
            ins(q[i].y,q[i].w);
        else
            ans[q[i].id]+=q[i].tag*ask(q[i].y);
    }
    for(int i=1; i<=Q; i++)
        printf("%lld\n",ans[i]);
}
signed main()
{
    scanf("%lld",&t);
    for(int i=1; i<=t; i++)
        work();
    return 0;
}

CDQ分治

 

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define EXP exp(1)
#define pppp cout<<endl;
#define EPS 1e-8
#define LL long long
#define ULL unsigned long long     //1844674407370955161
#define INT_INF 0x3f3f3f3f      //1061109567
#define LL_INF 0x3f3f3f3f3f3f3f3f //4557430888798830399
// ios::sync_with_stdio(false);
// 那麼cin, 就不能跟C的 scanf,sscanf, getchar, fgets之類的一起使用了。
const int dr[]= {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[]= {-1, 1, 0, 0, -1, 1, -1, 1};
inline int read()//輸入外掛
{
    int ret=0, flag=0;
    char ch;
    if((ch=getchar())=='-')
        flag=1;
    else if(ch>='0'&&ch<='9')
        ret = ch - '0';
    while((ch=getchar())>='0'&&ch<='9')
        ret=ret*10+(ch-'0');
    return flag ? -ret : ret;
}

const int N=1000050;
int c[N];
int ans[N];
int n,tim;
int lowbit(int x)
{
    return x&(-x);
}
void add(int x,int w)
{
    while(x<=n)
    {
        c[x]+=w;
        x+=lowbit(x);
    }
}
int getsum(int x)
{
    int ret=0;
    while(x)
    {
        ret+=c[x];
        x-=lowbit(x);
    }
    return ret;
}
struct Node
{
    int t;
    int x,y;
    int w,ot,id;
    Node() {}
    Node(int t,int x,int y,int w,int ot,int id):t(t),x(x),y(y),w(w),ot(ot),id(id) {}
    bool operator < (const Node &b)const
    {
        if(x!=b.x)
            return x<b.x;
        if(y!=b.y)
            return y<b.y;
        return id<b.id;
    }
} q[N],tmp[N];

void CDQ(int l,int r)
{
    if(l==r)
        return;
    int mid=(l+r)>>1;
    for(int i=l; i<=r; ++i)
    {
        if(q[i].t<=mid&&q[i].ot==1)
            add(q[i].y,q[i].w);
        if(q[i].t>mid&&q[i].ot==2)
            ans[q[i].id]+=q[i].w*getsum(q[i].y);
    }
    for(int i=l; i<=r; ++i)
        if(q[i].t<=mid&&q[i].ot==1)
            add(q[i].y,-q[i].w);
    int t1=l-1,t2=mid;
    for(int i=l; i<=r; ++i)
        if(q[i].t<=mid)
            tmp[++t1]=q[i];
        else
            tmp[++t2]=q[i];
    for(int i=l; i<=r; ++i)
        q[i]=tmp[i];
    CDQ(l,mid);
    CDQ(mid+1,r);
}
LL FindValue(LL n,LL x,LL y)
{
    LL a,b,p,c,ans;
    p=(n+1)>>1;
    a=abs(x-p);
    b=abs(y-p);
    c=max(a,b);

    ans=(c*2-1)*(c*2-1);

    if(x==p+c)
    {
        ans+=(c*2)*3-1;
        ans+=y-(p-c);
        ans=n*n-ans;
        return ans;
    }
    else if(x==p-c)
    {
        ans+=c*2-1;
        ans+=(p+c)-y;
        return n*n-ans;
    }
    else if(y==p+c)
    {
        ans+=(p+c-1)-x;
        return n*n-ans;
    }
    else if(y==p-c)
    {
        ans+=c*4-1;
        ans+=x-(p-c);
        return n*n-ans;
    }
}
int cal(LL n,LL x,LL y)
{
    LL res=FindValue(n,x,y);
    int ret=0;
    while(res)
    {
        ret+=res%10;
        res/=10;
    }
    return ret;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        tim=0;
        int tot=0;
        int m,Q;
        scanf("%d%d%d",&n,&m,&Q);
        for(int i=1; i<=m; ++i)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            int val=cal(n,x,y);
            q[++tot]=Node(++tim,x,y,val,1,0);
        }
        for(int i=1; i<=Q; ++i)
        {
            int x1,y1,x2,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            ans[i]=0;//++tim1;
            q[++tot]=Node(++tim,x1-1,y1-1,+1,2,i);
            q[++tot]=Node(++tim,x2,y2,+1,2,i);
            q[++tot]=Node(++tim,x1-1,y2,-1,2,i);
            q[++tot]=Node(++tim,x2,y1-1,-1,2,i);
        }
        sort(q+1,q+tot+1);
        CDQ(1,tot);
        for(int i=1; i<=Q; ++i)
            printf("%d\n",ans[i]);
    }

    return 0;
}

主席樹在線

https://blog.csdn.net/Endeavor_G/article/details/100188848

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