The beautiful values of the palace 2019南京网络赛

5 篇文章 0 订阅
2 篇文章 0 订阅

https://nanti.jisuanke.com/t/41298

扫描线,把所有点按照x排序,所有矩阵的查询拆成在[1--x1-1]这个位置减去y在[y1,y2]的所有点的值,在[1---x2]这个位置加上y在[y1,y2]的所有点的值。

然后枚举x坐标从左到右,先把坐标为x的点在树状数组中b[y]中加val,然后再处理这个位置的查询,是减去的就减去,是加的就加

 

#include<bits/stdc++.h>
#define maxl 1000010
using namespace std;

int n,m,p;
typedef pair<int,long long> pr;
vector <pr> inx[maxl];
struct qry
{
	int y1,y2,id;
};
vector <qry> add[maxl],mov[maxl];
long long ans[maxl],num[maxl],b[maxl];

inline long long calc(int x,int y)
{
	int dx=min(n-x+1,x),dy=min(n-y+1,y),t=min(dx,dy);
	int len=n-2*(t-1);
	long long ret=num[t-1]+1;
	if(t==(n/2+1))
		return ret;
	if(x==n-t+1)
		return ret+(n-t+1)-y;
	else
	{
		ret+=len-1;
		if(y==t)
			return ret+(n-t+1)-x;
		else
		{
			ret+=len-1;
			if(x==t)
				return ret+y-t;
			else
			{
				ret+=len-1;
				return ret+x-t;
			}
		}
	}
	
}

inline void prework()
{
	scanf("%d%d%d",&n,&m,&p);	
	for(int i=0;i<=n;i++)
	{
		add[i].clear();mov[i].clear();
		inx[i].clear();
	}
	for(int i=1;i<=n/2;i++)
		num[i]=num[i-1]+4*(n-2*(i-1))-4;
	num[n/2+1]=num[n/2]+1;
	int x1,y1,x2,y2;long long val,d;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&x1,&y1);
		val=calc(x1,y1);
		d=0;
		while(val>0)
		{
			d+=val%10;
			val/=10;
		}
		inx[x1].push_back(make_pair(y1,d));
	}
	for(int i=1;i<=p;i++)
	{
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		mov[x1-1].push_back(qry{y1,y2,i});
		add[x2].push_back(qry{y1,y2,i});
	}
}

inline void upd(int i,long long x)
{
	while(i<=n)
	{
		b[i]+=x;
		i+=i&-i;
	}
}

inline long long sum(int i)
{
	long long ret=0;
	while(i)
	{
		ret+=b[i];
		i-=i&-i;
	}
	return ret;
}

inline void mainwork()
{
	for(int i=1;i<=n;i++)
		b[i]=0;
	for(int i=1;i<=p;i++)
		ans[i]=0;
	pr d;int y2,y1,id;
	for(int i=0;i<=n;i++)
	{
		int l=inx[i].size();
		for(int j=0;j<l;j++)
		{
			d=inx[i][j];
			upd(d.first,d.second);	
		}
		l=add[i].size();
		for(int j=0;j<l;j++)
		{
			id=add[i][j].id;
			y1=add[i][j].y1;y2=add[i][j].y2;
			ans[id]+=sum(y2)-sum(y1-1);
		}
		l=mov[i].size();
		for(int j=0;j<l;j++)
		{
			id=mov[i][j].id;
			y1=mov[i][j].y1;y2=mov[i][j].y2;
			ans[id]-=sum(y2)-sum(y1-1);
		}
	}	
}

inline void print()
{
	for(int i=1;i<=p;i++)
		printf("%lld\n",ans[i]);
}

int main()
{
	int t;
	scanf("%d",&t);
	for(int i=1;i<=t;i++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值