北京Day 21

今天接着颓废。

T1 

题目大意:求m段区间的最大空隙。

题解:其实这题卡读题,读懂了题就是一道大水题。

T1AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
#include<set>
#include<map>
using namespace std;
inline int re_ad()
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-48,ch=getchar();}
	return x*f;
}
inline char read(){char ch=getchar();while(ch!='E'&&ch!='W')ch=getchar();return ch;}
int n,w,u,v,t1,t2,m,cnt;
struct chuan{double l,r;}a[2000000];
bool cmp(chuan x,chuan y){if(x.l!=y.l)return x.l<y.l;return x.r>y.r;}
int main()
{
	register int i,j,fla,l,ct,cw;
	register char op;
	register double x,lt,rt,r=0,ans=0;
	n=re_ad();w=re_ad();u=re_ad();v=re_ad();t1=re_ad();t2=re_ad();
	for(i=0;i<n;++i)
	{
	op=read();x=1.0*i*w/(1.0*v);
	if(op=='E')fla=-1;else fla=1;
	m=re_ad();
	for(j=1;j<=m;++j)
	{
	l=re_ad();
	ct=re_ad()*fla;cw=ct+l;
	lt=(1.0*ct)/(1.0*u)-x;rt=(1.0*cw)/(1.0*u)-x;
	if(lt>t2||rt<t1)continue;
	a[++cnt].l=lt;a[cnt].r=rt;
	}
	}
	sort(a+1,a+cnt+1,cmp);
	r=t1;x=1.0*w/(1.0*v);
	for(i=1;i<=cnt;++i)
	{
	ans=max(ans,a[i].l-x-r);
	r=min(1.0*t2,max(r,a[i].r));
	}
	ans=max(ans,t2-r);
	printf("%.8lf",ans);
}

T2

题目大意:有(N+1)个城市,0 是起点 N 是终点,车每走 1 个单位距离消耗 1 个单位的汽油,油箱的容量是 T。给出每个城市到下一个 城市的距离 D,以及当地的油价 P,求走完整个旅途最少的花费。如果无法从起 点到达终点输出-1。n<=1e5。

题解:贪心,用单调栈计算当前的城市 的油价一直到后面哪个城市都是最小的,设这个数为 y,当前城市为 x,那么从 x 到 y+1 中间的道路消耗的油都应该尽量在 x 加。

T2AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
#include<set>
#include<map>
using namespace std;
inline int re_ad()
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-48,ch=getchar();}
	return x*f;
}
inline int mi(int x,int y){return x<y?x:y;}
int n,T;
int my[100010],yj[100010];
int z[100010],top=0,nex[100010];
long long ans=0,sum[100010];
int main()
{
	register int i,j;
	register long long x=0,y;
	n=re_ad();T=re_ad();
	for(i=1;i<=n;++i){my[i]=re_ad();sum[i]=sum[i-1]+my[i];yj[i]=re_ad();if(my[i]>T){cout<<-1<<endl;return 0;}}
	for(i=1;i<=n+1;++i)
	{
	while(top&&yj[z[top]]>=yj[i])nex[z[top--]]=i;
	z[++top]=i;
	}
	for(i=1;i<=n;++i)
	{
	x-=my[i-1];
	y=min(1ll*T,sum[nex[i]-1]-sum[i-1]);
	if(y>x){ans+=1ll*(y-x)*yj[i];x=y;}
	}
	cout<<ans<<endl;return 0;
	return 0;
}

T3 51nod1850 抽卡大赛

题目大意:每个人抽卡有 Mi 种可能,得到的卡能力值为 Aij 代价为 Gij 的可能性为 Pij ,需要将一轮比赛后所得的收入的 Gij% 交给主办方。每轮比赛每个人都随机抽取卡片,待全部人抽取完毕后迚行排名(按照 A 从大到小排),排在第 i 位的人有 Vi 的收入。现在主办方想知道一轮比赛后每个人的期望收入。

题解:

对于一个权值A,只有大于它的值会对它的排名造成影响,所以我们将所有的A值放在一起排序,考虑如何求出Ai的期望排名。

如果把值A在n个人中的期望排名看做一个生成函数,那么大于A的数会让A的排名增大,要统计第i个人的选择Ai对他的收益的贡献, 只需要把这时的多项式除去第i个人的式子,就可以得到Ai对于其它n-1个人的期望排名了,乘上选择Ai的概率再除去代价加到ans[i]中即可。

当权值变动时,F(x)只会有一项变动,且变动的项均为一次项,可以O(n)进行一次除法和乘法。(其实这里类似于DP)

具体写代码的时候可以让多项式保持在n-1项,求Ai的贡献时把i的多项式除去,把i-1的多项式乘进来。

T4 luoguP4680

此题神题,此讨论帖更是神帖。

具体做法自行查阅。


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值