Test 2022.09.29

今天是SHOI专场

T1 智力大冲浪

分析

确实是智力题了,考虑贪心策略:优先安排价值大的,时间能往后就往后,这样前面能选更多东西,如果当前的时间已经有安排了,那么就往前一个位置挪,直到当前时间没有被安排,如果为0,那么久不选当前的东西了。

Code

点击查看代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define int long long
using namespace std;
const int maxn=600;
struct present{int date,fine;}a[maxn];
bool cmp(present a,present b){return a.fine!=b.fine?a.fine>b.fine:a.date>b.date;}
int n,m;
int vis[maxn];
int all=0;
signed main()
{
scanf("%lld%lld",&m,&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i].date);
for(int i=1;i<=n;i++)scanf("%lld",&a[i].fine),all+=a[i].fine;
sort(a+1,a+n+1,cmp);
int sum=0;
for(int i=1;i<=n;++i)
{
int p=a[i].date;
while(vis[p]==1)p--;
if(p==0){continue;}
vis[p]=1,sum+=a[i].fine;
}
printf("%lld",m-(all-sum));
return 0;
}
/*
10000 7
4 2 4 3 1 4 6
70 60 50 40 30 20 10
10
7
1 2 2 4 2 5 5
0 1 1 1 2 100 1
*/

T2 发微博

分析

本来想着暴力建图,对于每一个加号都暴力遍历然后让ansi++,然而人傻不会vector的删除(好像这样可以骗到80pts),最后只做了一个50pts的暴力。

突破口

就是题面中的"保证操作合法:即 + x y 时 x 和 y 一定不是好友,而 − x y 时 x 和 y 一定是好友"

再次分析

上一句话是什么意思呢?这是在变相告诉我们:给出的操作一定是若干对"+ -"!!。
可能这个时候还是没反应过来,很正常,看下去就懂了。
很显而易见的是,只有被囊括在这一对对"+"里面的"!"操作才会对答案进行贡献,如果暴力遍历每一对所有+,里的内容是完全会超时的。
这个时候我们就可以考虑借助后缀和的思想统计,众所周知,"!"操作只有在"+"进行后才能对答案产生贡献,在“-”操作进行后停止对答案产生贡献。
那我们不妨假设"+"之后的"!"操作会一直对答案产生贡献,不受"-"的影响,这样就会多算一部分的贡献值,考虑如何去消除它?很简单,只要减去"-"之后"!"的数量就行了。
这样的话我们就不需要暴力遍历了,只用,倒序遍历,分别统计每个人对应"!"的后缀和sum.
对于每一个"+ x y"的操作,我们把ansx+sumy,ansy+sumx
对于每一个"- x y"的操作,我们把ansxsumy,ansysumx
接下来应该不用讲了 上代码

Code

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+100;
int ans[maxn],cnt[maxn];
char a[maxn];int x[maxn],y[maxn];
int main()
{
ios::sync_with_stdio(0);
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>a[i]>>x[i];
if(a[i]=='+'||a[i]=='-')cin>>y[i];
}
for(int i=m;i>=1;i--)
{
if(a[i]=='!')cnt[x[i]]++;
else if(a[i]=='-')ans[x[i]]-=cnt[y[i]],ans[y[i]]-=cnt[x[i]];
else if(a[i]=='+')ans[x[i]]+=cnt[y[i]],ans[y[i]]+=cnt[x[i]];
}
for(int i=1;i<n;i++)cout<<ans[i]<<' ';
cout<<ans[n];
return 0;
}

T3 发牌

心路历程

考场上面再次成功想歪了,今天真是一个正解没打出来,以为是在链表上面维护倍增,结果维护就直接g掉,只有20pts

分析&正解

对于一次销牌的操作Ri,其实就是把当前序列中前Rimodlen个元素按顺序放到序列最后的位置,然后输出当前排在第一位的元素,记上一次跳到的位置是pos的话,实际上就是在查询这整个序列中第(pos+Ri)modlen+1小的数是谁,输出以后把他剔除掉(或许你可以把这个操作理解成循环队列?)有点难以解释,怎么说呢?从上一个查询的位置开始再跳Ri个,相当于就是查询现有区间内第(pos+Ri)modlen+1小,然后把pos迭代成(pos+Ri)modlen,len,那么就是权值线段树的板子题了。

点击查看代码

T4 阶乘字符串

Tobecontinued

posted @   Hanggoash  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
动态线条
动态线条end
点击右上角即可分享
微信分享提示