题目链接:https://nanti.jisuanke.com/t/41298
题目大意:给一个n*n的矩阵,矩阵的值成螺旋状,找到m个格子,每个格子的值为原先数字的位数和,其他的全为0,询问p次给定矩阵的权值。
题解:首先快速求出这个点的原先的值,寻找这个点在那个环上,在四个边上那个边上,就能求出来了,线段树前缀和,扫描线的做法,一次查询分成两次。
代码:
#include <bits/stdc++.h>
#define ls x<<1
#define rs x<<1|1
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
struct node{
int x,y,w;
}s[maxn];
struct node1{
int ce,l,r,id,fu;
}v[maxn*3];
ll T,n,m,p; ll a[maxn];
int _val(ll x,ll y){
ll val=min(min(x,n-x+1),min(y,n-y+1));
int lx=n-val+1,ly=n-val+1;
int la=val,lb=n-val+1;
ll ans;
if(x==lb||y==la)
ans=abs(x-lx)+abs(y-ly)+a[val-1]+1;
else if(x==la||y==lb)
ans=a[val]-abs(x-lx)-abs(y-ly)+1;
int num=0;
while(ans) {num+=ans%10; ans/=10;}
return num;
}
ll tree[maxn*4]; ll ans[maxn];
void init(){
memset(ans,0,sizeof(ans));
memset(tree,0,sizeof(tree));
for(ll i=1;i<=(n+1)/2;i++){
a[i]=(n-(i-1LL)*2LL)*(n-(i-1LL)*2LL);
}
for(int i=1;i<(n+1)/2;i++) a[i]-=a[i+1];
for(int i=2;i<=(n+1)/2;i++) a[i]+=a[i-1];
}
int cmp(node pp,node qq){
return pp.x<qq.x;
}
int cmp1(node1 ppp,node1 qqq){
return ppp.ce<qqq.ce;
}
void add(int x,int l,int r,int pos,ll val){
if(l==r) {
tree[x]+=val; return ;
}
int mid=(l+r)>>1;
if(pos<=mid) add(ls,l,mid,pos,val);
else add(rs,mid+1,r,pos,val);
tree[x]=tree[ls]+tree[rs];
}
ll query(int x,int l,int r,int L,int R){
if(l==L&&r==R){
return tree[x];
}
int mid=(l+r)>>1;
if(R<=mid) return query(ls,l,mid,L,R);
else if(L>mid) return query(rs,mid+1,r,L,R);
else return query(ls,l,mid,L,mid)+query(rs,mid+1,r,mid+1,R);
}
int main()
{
scanf("%lld",&T);
while(T--){
scanf("%lld %lld %lld",&n,&m,&p);
init();
for(int i=1;i<=m;i++){
scanf("%d %d",&s[i].x,&s[i].y);
s[i].w=_val(s[i].x,s[i].y);
}
sort(s+1,s+1+m,cmp);
int t=0;
for(int i=1;i<=p;i++){
int u,l,r;
scanf("%d %d",&u,&l);
v[++t].ce=u-1; v[t].l=l; v[t].id=i; v[t].fu=-1;
scanf("%d %d",&u,&r);
v[++t].ce=u; v[t].l=v[t-1].l;
v[t].r=v[t-1].r=r; v[t].id=i; v[t].fu=1;
}
sort(v+1,v+1+t,cmp1);
int l=1,ll=1;
for(int i=0;i<=n;i++){
while(s[l].x==i&&l<=m){
add(1,1,n,s[l].y,s[l].w);
l++;
}
while(v[ll].ce==i&&ll<=t){
ans[v[ll].id]+=query(1,1,n,v[ll].l,v[ll].r)*v[ll].fu;
ll++;
}
}
for(int i=1;i<=p;i++) {
printf("%lld\n",ans[i]);
}
}
return 0;
}