NOIP2018模拟赛 (二维差分)2018 10 22 T1

题面:

 

算法:对一个“斜着的”数组差分!

题解:

对一个三角形斜着打标记(差分),对此数组进行差分!

代码如下:

1、81分(47分稳过,两组数据卡常,lemon会自动重测!)

算法:对一维进行差分,另一维暴力修改(一维差分很好写,也不难想)

注意:min(,)!!!

否则如果超出了n还去修改,可能 就 会RE!   对拍了一个小时,一直RE!!!

代码如下:

(如果你没有得到81分,① 自己写读优,这样就可以让lemon自动重测!② 可能老师忘记开O2了!

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cctype>
#include <queue>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#define ll long long 
#define N 1005
using namespace std;
struct node 
{
	int a,b,c,d;
}e[300005];
ll aa[N][N];
ll sum[N][N];

inline int read()
{
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
int main()
{
	freopen("u.in","r",stdin);
	freopen("u.out","w",stdout);
	//printf("%d\n",(sizeof(aa)+sizeof(sum)+sizeof(e))/1024/1024);
	int n,m;
	//scanf("%d%d",&n,&m);
	n=read(),m=read();
	for(int i = 1;i <= m;i++)
	{
		e[i].a=read(),e[i].b=read(),e[i].c=read(),e[i].d=read();
		//scanf("%d%d%d%d",&e[i].a,&e[i].b,&e[i].c,&e[i].d);
	}
	if(m==0) 
	{
		puts("0");
		return 0;
	}
	//printf("%d\n",e[2979].b);
	for(int i = 1;i <= m;i++)
	{
		int a,b,c,d;
		a=e[i].a,b=e[i].b,c=e[i].c,d=e[i].d;
		ll tt=1;
		for(int j = a;j < min(a+c,n+1);j++)
		{	
			/*if(b==1||b+tt==1)
			{
				int u=1;
				if(j==12)
				{
					u=2;
				}
			}*/ 
			aa[j][b]+=d;
			if(tt+b>n||tt>n) continue;
			aa[j][b+tt]-=d;
			/*if(aa[12][1]<0)
			{
				printf("%d %d %d\n",i,j,tt);
				printf("%d\n",e[i].b);
				for(int z =1;z <= 12;z++)
				{
					for(int o = 1;o <= 5;o++)
					{
						printf("%d ",aa[z][o]);
					}
					puts("");
				} 
				int qwe=1;
				qwe=2;
				return 0;
			}*/
			tt++;
			
		}
	}
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= n;j++)
		{
			sum[i][j]=sum[i][j-1]+aa[i][j];
			/*if(sum[i][j]<0) 
			{
				printf("%d %d\n",i,j);
				return 0 ;
			}*/ 
		}
	}
	ll ans=sum[1][1];
	//printf("%d \n",sum[12][1]);
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= n;j++)
		{
			
			if(i==1&&j==1) continue;
			ans^=sum[i][j];
		}
	}
	printf("%lld\n",ans);
	return 0 ;
} 

2、AC

时间复杂度O(n^2)

#include<bits/stdc++.h>
#define ll long long
#define N 1005 
using namespace std;
int n,q;
ll a[N][N],sum[N][N],ans;
void add_a(int x,int y,int w)
{
	if(x<=n&&y<=n) a[x][y]+=w;
}
void add_b(int x,int y,int w)
{
	if(x<=n&&y<=n) sum[x][y]+=w;
}
int main()
{
	freopen("u.in","r",stdin);
	freopen("u.out","w",stdout);
	scanf("%d%d",&n,&q);
	while(q--)
	{
		int r,c,l,s;
		scanf("%d%d%d%d",&r,&c,&l,&s);
		add_a(r,c,s);
		add_a(r+l,c+l,-s);
		add_b(r+l,c,-s);
		add_b(r+l,c+l,s);
	}
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= n;j++)
		{
			if(i>1) a[i][j]+=a[i-1][j-1]+a[i-1][j]-a[i-2][j-1];
			else a[i][j]+=a[i-1][j-1]+a[i-1][j];
			sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
			ans^=(a[i][j]+sum[i][j]);
		}
	}
	printf("%lld\n",ans);
	return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值