2020.1.8 星期三
寒假回来了,该上学了.
寒假终于打了第一场div2,之前都是天天喊着要打,然后天天恰好错睡 过,补题,然而终于有机会来一场真的了。这次差点又记错时间,多亏了罗切斯特的老哥提醒,让27号晚上九点还在跑步的我突然意识到还有一个小时比赛就开始了,不然又2019年真的就unrated了。
好吧,事实上还真的挺失败的,只写了第一道题,第一道题是一道简单的php,这里不说了,刚开始忘把freopen去掉还wa了一发。
然后第二题就比较舒(cao)服(dan)了,群里一部分人都几乎是秒过了B,我原来以为我自己可能是个好的翻译,结果后来发现我连翻译都做不好,回去默默地把托福110+的成绩扔进垃圾桶。刚开始我以为是要求不限个数删除,删掉几个才能听完整的,那我想就是简单贪心嘛,样例也过了,就提交了
WA x 1
WA的猝不及防使我感到事情有些蹊跷,再一读题发现原来是让我们求能够听的最多的个数,但是题意总感觉有些前后矛盾,但是顾不得那么多了,重新写了代码之后,用了前缀和和优先队列之后搞了下过了样例,交了上去
WA x 2
我哭辽这什么情况,我和一位国内的同学几乎是抱着哭,这道题看上去是水题,然而我真的没想到会栽倒在这个上面,然后我研究了下我的算法,发现复杂度和算法应该都没问题,如果有问题,那只能说明是我的理解出错了。
仔细读题,发现是让求删掉一个下标上的数字使圣诞老人听到的颂词是最多的,原来是下标,哭了哭了。另外说一下,我发现这个问题已经是1小时40分钟的时候了,久未熬夜的我脑子着实已经不太清楚了,用lis和前缀和搞了下之后发现可以过样例了,继续提交
WA x 3
此时比赛已经接近尾声,只能抱憾而终了。
C题我看了,当时觉得可能是叠落方块那样用并查集的样子,不过后来发现其实只是简单模拟,并不复杂,饿,赛后补题,B我用答案的方法试了试,在第五个点TLE了,也在意料之内,毕竟python和c++还是有区别的,这里借用一下@Mr.Skirt老哥的方法,他的方法是比较合理的,维护一个堆然后依次把所有元素推进去,然后用前缀和判断是否可以成为删掉的节点,因为在队列中一个大的的存在势必会增加在这点间断的可能性,所以这样做简化了代码。我也是后来想了好久才明白,其实用前缀和也应该是可以,不过我当时想的是求第一个开始的降序子序列然后和原数组进行比较,没意识到这样做很容易就出毛病了。代码如下:
#include <bits/stdc++.h>
using namespace std;
#define limit 100000 + 5//防止溢出
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3ff
#define lowbit(i) i&(-i)//一步两步
#define EPS 1e-6
#define ff(a) printf("%d\n",a );
#define MOD 1e9 + 7
typedef long long ll;
void read(int &x){
char ch = getchar();x = 0;
for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
}//快读
int read(){
int x;
char ch = getchar();x = 0;
for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return x;
}//快读
int kase;
ll n , m;
ll a[limit],sum[limit];
int main(){
//freopen("C:\\Users\\administrator01\\CLionProjects\\untitled14\\data.txt", "rt", stdin);
scanf("%d", &kase);
while(kase--){
scanf("%lld%lld" , &n, &m);
sum[0] = 0;
for(int i = 1 ; i <= n ; ++i){
scanf("%lld", &a[i]);
sum[i] = sum[i - 1] + a[i];//前缀和
}
if(sum[n] <= m){
puts("0");
continue;
}
priority_queue<pair<ll,int>>q;
int ans = 0;
for(int i = 1 ; i <= n ; ++i){
q.push({a[i], i});
if(sum[i - 1] <= m){
ans = i;
}
if(sum[i] <= m + q.top().first){//等于全加起来
ans = q.top().second;
}
}
ff(ans)
}
return 0;
}
这个代码是Mr.Skirt老哥的,我放在这里只是为了当个仓库,如果有不妥的地方我会把它删掉。
C题,嗯,并不是并查集,只是简单的构造,不过得开ull,不禁让人想到了今年csp的D1 hhhhh
刚开始写挂了,去看tutorial,我发现我的代码和答案惊人的相似,当时觉得没毛病为什么挂我,不过后来cf提示说int爆了,然后换用ull一发入魂,ok就这么多了。
代码
#include <bits/stdc++.h>
using namespace std;
#define limit 100000 + 5//防止溢出
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3ff
#define lowbit(i) i&(-i)//一步两步
#define EPS 1e-6
#define ff(a) printf("%d\n",a );
#define MOD 1e9 + 7
typedef unsigned long long ll;
void read(int &x){
char ch = getchar();x = 0;
for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
}//快读
int read(){
int x;
char ch = getchar();x = 0;
for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return x;
}//快读
int kase;
ll n , m;
ll gift[limit] , seq[limit];
ll cost(ll k){
return 2 * k + 1;
}
int pos[limit];//映射
int main(){
//freopen("C:\\Users\\administrator01\\CLionProjects\\untitled14\\data.txt", "rt", stdin);
kase = read();
while(kase--){
scanf("%lld%lld" , &n, &m);
for(int i = 1 ; i <= n ; ++i){
scanf("%lld", &gift[i]);
pos[gift[i]] = i;//反向映射
}
for(int i = 1 ; i <= m ; ++i){
scanf("%lld" , &seq[i]);
}
int fpos = -1;//第一个的位置,初始化为无穷小
ll ans = m;//答案//原本需要的,一个一个拿出来的,现在不需要要
for(int i = 1 ; i <= m ; ++i){
if(pos[seq[i]] > fpos){
ans += 2 * (pos[seq[i]] - i);//1需要把东西送出去,花疫苗
fpos = pos[seq[i]];
}
}
printf("%lld\n", ans);
//首先先找到第一个的位置然后再找后面的
}
return 0;
}