test 三角形 (乱搞)

本文介绍了一种特殊类型的编程题目解决方案——乱搞题解。该方案使用线段树进行区间修改与查询,最终采用差分技巧优化。文章详细解释了如何计算每个修改对查询的影响,并通过前缀和数组简化计算过程。整体时间复杂度为O(q/k*(n^2)+q*k),通过合理选择参数k实现有效率的解答。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



题解:乱搞

这个题测试的时候写的线段树区间修改区间查询,然后get到50分。。。。

这个题的正解其实就是个乱搞。

每一个修改对每一个询问的影响可以O(1)的计算,需要判断两个三角形的位置关系,然后计算重叠部分的点数。

然后我们可以对每个修改进行差分,当累积的未处理的操作数达到一定值的时候,我们就将每个位置的数查询出来,然后记录到前缀和数组中,每次这么做的时间复杂度是O(n^2)

然后每次查询的时候只需要查询前缀和数组,然后再o(1)计算未加入前缀和的修改对当前询问的影响即可。

时间复杂度O(q/k*(n^2)+q*k) 当k=1000的时候就可以通过了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define N 1003
#define LL long long
using namespace std;
LL sum[N][N],ch[N][N];
int n,m,posx[N*100],posy[N*100],a1[N*100];
void change(int x,int y,int a)
{
	for (int i=x;i<=x+a-1;i++){
		int y1=y+i-x;
		ch[i][y]++; ch[i][y1+1]--;
	}
}
void build()
{
	memset(sum,0,sizeof(sum));
	for (int i=1;i<=n;i++)
	 {
	 	LL t=0;
	 	for (int j=1;j<=i;j++) t+=ch[i][j],sum[i][j]=sum[i][j-1]+t;
	 }
}
int main()
{
   freopen("delta.in","r",stdin);
   freopen("delta.out","w",stdout);
   scanf("%d%d",&n,&m);
   int k=0; int x1,y1,x2,y2;
   for (int i=1;i<=m;i++){
   	 int opt,x,y,a; scanf("%d%d%d%d",&opt,&x,&y,&a);
   	 if (opt==1) {
   	 	  k++; posx[k]=x; posy[k]=y; a1[k]=a; change(x,y,a);
   	 	  if (k==1000)  build(),k=0;
		}
	 else {
	 	LL ans=0;
	 	for (int j=x;j<=x+a-1;j++) ans+=sum[j][y+j-x]-sum[j][y-1];
	 	for (int j=1;j<=k;j++){
	 		if (posy[j]==y&&x<posx[j]||y<posy[j]) {
	 			x1=x; y1=y; 
	 			x2=posx[j]; y2=posy[j];
			 }
			else {
				x1=posx[j]; y1=posy[j];
				x2=x; y2=y;
			}
			x2=max(x2,x1+y2-y1);
			int len=max(min(x+a,posx[j]+a1[j])-x2,0);
			ans+=(LL)(len+1)*(LL)len/2;
		 }
		printf("%I64d\n",ans);
	 }
   }	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值