牛客NOIP暑期七天营-普及组4 D-火龙果画

小巫女从小就喜欢吃火龙果,她有一个梦想,就是用魔法变出许许多多美味可口的火龙果,这样她就可以天天享受火龙果的美味啦!

在一个二维平面上,小巫女用火龙果画出了许多图案,她想知道这些图案中最闪耀的一点的美观度有多大。

具体的,在初始美观度均为0的平面上,小巫女画出了 n 个等腰直角三角形(其直角边平行于坐标轴),并且使得三角形内部(包含边界)的整点增加了 c 的美观度。

一幅画作完成啦,你也要回答小巫女最初提问的问题呢!

如果她高兴了,说不定会送给你她最爱吃的火龙果呢!

输入描述:

第一行,一个整数 n。
接下来 n 行,每行五个整数 opt,x,y,l,c。(请注意:坐标轴x正方向向下,y轴正方向向右)
其中,opt=1/2/3/4分别表示等腰直角三角形的直角点在左上、右上、左下、右下,其坐标为(x,y),直角边长为l,增加的美观度为c。

输出描述:

第一行,包含一个整数ans,表示二维平面中最大的美观度是多少。

示例1

输入

复制

2
1 1 1 1 1
4 3 3 2 2

输出

复制

2

说明

每个点的权值为:
1 1 2
1 2 2
2 2 2

备注:

 

思路

废话:一开始想了很多,什么二维前缀和,悬线法之类 的,想从里面找到灵感,后来都没用,不过忽然想到昨天线段树例题看到的一点东西,就想明白了应该怎么做

首先,假如我们从第i行,从左往右遍历过去,我们发现进入三角形后就会得到对应的美观度,从这个三角形出去之后就会失去对应的美观度,那么怎么算进入,怎么算出去。

最左边的边是入边,最右边的边是出边,我们将入边上的每一个点+C(对应的美观度),出边往右平移一格的边(即虚线)上的每一个点-C,然后每一行从左到右进行前缀和运算,mmap[i][j].c+=mmap[i][j-1].c,每一次运算得到的最大值就是答案

PS1:代码中的bool类型变量rubian和chubian没有什么用,就是自己看的,可以不加

PS2:当然你也可以把最上面的边当做入边,下面的边当做出边,然后从上到下做前缀和运算,其中的关系不要搞晕就可以,我有个朋友把y当做行,x当做列,但是题目给你的(x,y),x是行,y是列,WA的自闭2333

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#define rep(i,s,e) for(int i=s;i<=e;i++)
#define rep1(i,s,e) for(int i=s;i<e;i++)
#define rep2(i,s,e,c) for(int i=s;i>=e;i--)
#define pfi(x) printf("%d\n",x)
#define pfl(x) printf("%lld\n",x)
#define pfn() printf("\n")
#define pfs() printf(" ")
#define sfi(x) scanf("%d",&x)
#define sfi1(x,y) scanf("%d%d",&x,&y)
#define sff(x) scanf("%lf",&x)
#define sfl(x) scanf("%lld",&x)
#define memset1(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
const int MAX = 1e4 + 50;
const int mod = 996873654;
struct node{
	bool rubian;
	bool chubian;
	ll c;
}mmap[1005][1005];
int main(){ 
	int n;
	sfi(n);
	memset1(mmap);
	for(int i=0;i<n;i++){
		int opt,x,y,l;
		ll c;
		scanf("%d%d%d%d%lld",&opt,&x,&y,&l,&c);
		if(opt==1){//左上 
			for(int j=x;j<=x+l;j++){
				mmap[j][y].rubian=true;
				mmap[j][y].c+=c;
			}
			int x1=x,y1=y+l+1;
			for(int k=0;k<=l;k++){
				mmap[x1+k][y1-k].chubian=true;
				mmap[x1+k][y1-k].c-=c;
			}
		}
		else if(opt==2){//右上 
			for(int j=x;j<=x+l;j++){
				mmap[j][y+1].chubian=true;
				mmap[j][y+1].c-=c;
			}
			int x1=x,y1=y-l;
			for(int k=0;k<=l;k++){
				mmap[x1+k][y1+k].rubian=true;
				mmap[x1+k][y1+k].c+=c;
			}
		}
		else if(opt==3){//左下 
			for(int j=x;j>=x-l;j--){
				mmap[j][y].rubian=true;
				mmap[j][y].c+=c;
			}
			int x1=x-l,y1=y+1;
			for(int k=0;k<=l;k++){
				mmap[x1+k][y1+k].chubian=true;
				mmap[x1+k][y1+k].c-=c;
			}
		}
		else{//右下 
			for(int j=x;j>=x-l;j--){
				mmap[j][y+1].chubian=true;
				mmap[j][y+1].c-=c;
			}
			int x1=x,y1=y-l;
			for(int k=0;k<=l;k++){
				mmap[x1-k][y1+k].rubian=true;
				mmap[x1-k][y1+k].c+=c;
			}
		}
	}
	ll mx=0;
	for(int i=1;i<=1000;i++){
		for(int j=1;j<=1000;j++){
//			printf("%lld ",mmap[i][j].c);
			mmap[i][j].c+=mmap[i][j-1].c;
			mx=max(mx,mmap[i][j].c);
		}
//		pfn();
	}
	pfl(mx);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值