P1311选择客栈
这是2011年提高组D1T2,是一个绿色的模拟题,不出所料,没写出代码来。
首先输入n个客栈的颜色和最低消费,然后根据“同颜色但不是一个客栈”以及“两个客栈之间必须有一个的最低消费<=p"确定出最大的住宿方案数。然后我首先想到了暴力法:for(第一个客栈){for(第二个客栈){for(咖啡厅)}}},显然2e5肯定超时(当然赛场上可以这么暴力去写),还想到了用区间dp......看到了一位大佬的思路。直接枚举第二个客栈,只要前面同颜色的客栈是符合要求的,那么此时ans就应该加上这个颜色客栈的总数。所以我们就要开一个cnt[]来存储每个颜色的客栈有几个,sum[]来存当前的方案数,last[]存这种颜色的最后一个客栈的位置。所以当枚举i时,只要其符合条件就把i转移到now上来,假如now>=last[],那么sum[]就是cnt[](其实差这两个值相差的是<=p的数量)。ans+=sum[color],cnt[color]++。因为当他不满足,只要他中间满足也是可以的,方案数再加上这种颜色的客栈数量。
1.当你去优化时间复杂度时,试着去掉数据,直接循环输入进行计算
2.不会写正解就写暴力,绝对不可以光想着看题解,要锻炼啊
3.不去看算法标签了wuwuwu
4.逻辑逻辑能力一定要提升啊
代码
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #define N 100001 using namespace std; int n,k,p; int ans=0; int last[N],cnt[N],sum[N]; int color,cafe; int now;//记录离客栈最近的 int main(){ cin>>n>>k>>p; for(int i=1;i<=n;i++){ cin>>color>>cafe; if(cafe<=p){//预算够 } if(now>=last[color]){//在后面 sum[color]=cnt[color]; } last[color]=i;//让他当这个颜色的最后一位 ans+=sum[color]; cnt[color]++;//桶排序,记录这个颜色客栈数量 } cout<<ans; return 0; }
待到oi十一月,我花开后百花杀。