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;
}
主席树在线