【题目描述】
有 N 个能量发射站排成一行,每个发射站i都有不相同的高度 Hi,并能向两边(当然两端的只能向一边)同时发射能量值为 Vi 的能量,并且发出的能量只被两边最近的且比它高的发射站接收。
显然每个发射站有可能接收 0 或 1 或 2 个其它发射站发来的能量,特别是为了安全,它受到的能量总和是我们很关心的。由于数据很多,请你帮助我们计算出接受了最多能量的发射站接受的能量是多少。
【数据范围】
1 <= N <= 50,000
1 <= hi <= 2,000,000,000
1 <= vi <= 10,000
【输入格式】
第1行: 一个整数 N
第2..N+1行:第 i+1 行有2个整数 Hi Vi,表示第i个发射站的高和发射的能量值。
【输出格式】
一行:一个发射站接收到的最大能量值。
【样例输入】
3
4 2
3 5
6 10
【样例输出】
7
蒟蒻表示还是不会
怎么办呢?
随机枚举信号塔求此塔的接收值+卡时
。。。。。。
然后居然又A了
RP已败光。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
using namespace std;
int m;
int z,ans;
struct self{int x,y;}s[50555]; //high->x power->y
int a,b,c;
int tall,num;
bool flag[50555];void eixt()
{cout<<z<<'\n';
}void work(int i)
{ans=0;int a,b,lt,rt;lt=rt=0;for(a=i-1;a>=1;a--){if(s[a].x>=s[i].x)break;if(s[a].x>=lt){ans+=s[a].y;lt=s[a].x;}}for(b=i+1;b<=m;b++){if(s[b].x>=s[i].x)break;if(s[b].x>rt){ans+=s[b].y;rt=s[b].x;}}z=max(z,ans);
}int main()
{freopen("mooo.in","r",stdin);freopen("mooo.out","w",stdout);scanf("%d",&m);for(a=1;a<=m;a++){scanf("%d%d",&s[a].x,&s[a].y);if(s[a].x>tall){tall=s[a].x;num=a;}}flag[num]=1;work(num);while((double)clock()/CLOCKS_PER_SEC<=0.91){ans=0;a=(rand()+rand())%m+1;while(flag[a]){a=(rand()+rand())%m+1;if((double)clock()/CLOCKS_PER_SEC>=0.93){eixt();return 0;}}flag[a]=1;work(a);}eixt();return 0;
}
还要ORZ XPF大神
我们可以先考虑向左发射信号
再考虑向右发射信号
用一个栈维护i前(或后)的第一个比h[i]高的塔的编号
先考虑向左发射的情况
对于栈顶top对应的ht和wt
如果当前i站的hi=>ht则需要找到第一个比hi大的ht 需要top--
因为stack的push是从前向后的 所以第一个满足ht>hi的top肯定是i前面第一个比h大的站
l[stack[top]]+=s[i].w; 同时i进栈
如果当前i站的hi<ht 表示i前的最低高度大于hi t站可以接收到i的信号
此时只需将i进栈 l[stack[top]]+=s[i].w;
正着一遍 反着一遍 ans=max(ans,l[i]+r[i]);
#include<iostream>
#include<cstdio>
using namespace std;
const int lim=50555;
int stack[lim];
int top;int l[lim],r[lim];struct self{int h,w;}s[lim];
int m,a,b,c;void left()
{int a,b;top=1;stack[1]=1;for(a=2;a<=m;a++){if(s[stack[top]].h>s[a].h){l[stack[top]]+=s[a].w;top++;stack[top]=a;}else{while(s[stack[top]].h<=s[a].h&&top>0)top--;if(top>=1)l[stack[top]]+=s[a].w;top++;stack[top]=a;}}
}void right()
{int a,b;top=1;stack[1]=m;for(a=m-1;a>=1;a--){if(s[stack[top]].h>s[a].h){l[stack[top]]+=s[a].w;top++;stack[top]=a;}else{while(s[stack[top]].h<=s[a].h&&top>0)top--;if(top>=1)l[stack[top]]+=s[a].w;top++;stack[top]=a;}}
}void print()
{int a,ans=0;for(a=1;a<=m;a++)ans=max(ans,l[a]+r[a]);cout<<ans<<'\n';
}int main()
{freopen("mooo.in","r",stdin);freopen("mooo.out","w",stdout);scanf("%d",&m);for(a=1;a<=m;a++)scanf("%d%d",&s[a].h,&s[a].w);left();right();print();return 0;
}