2023/8/15 模拟赛题解
2023/8/15 模拟赛题解
T1 Simfonija
准确来说场上只有这道是自己现做的(另外两道都是原题)。
题意
给定两个长度为
思路
首先我们可以考虑
我们发现,答案就是这些黑线覆盖的面积。(想象一下从每一条黑线两侧延伸下来两条边,形成若干个矩形)
现在我们来考虑
假如红线现在向上平移,设绿色面积为
但是我们还有
代码:
#include<bits/stdc++.h> using namespace std; const int N = 1e5+100; const int M = 2e6+100, del = 2000000; inline int read(){ int x = 0, f = 1; char ch = getchar(); while(ch<'0' || ch>'9') {if(ch == '-') f = -1; ch = getchar();} while(ch>='0'&&ch<='9') {x = x*10+ch-48, ch = getchar();} return x * f; } int n, K; int a[N], b[N], d[N]; int e[N]; int ed[N]; int id[M<<1], idx; int main(){ // freopen("simfonija.in", "r", stdin); // freopen("simfonija.out", "w", stdout); n = read(), K = read(); for(int i = 1; i<=n; ++i){ a[i] = read(); } for(int i = 1; i<=n; ++i){ b[i] = read(); } for(int i = 1; i<=n; ++i){ d[i] = b[i] - a[i]; } sort(d+1, d+n+1); for(int i = 1; i<=n; ++i){ if(i == n || d[i+1]!=d[i]){ id[d[i]+del] = ++idx; ed[idx] = i; }//预处理每段黑边的右端点。 } int len = (n+1-K)/2; int X = d[len]; long long ans = 0; for(int i = 1; i<=(n-K); ++i){ ans+=abs(d[i]-X); }//左侧不选的答案 int lst = X; long long ret = ans; for(int i = 1; i<=K; ++i){ int nX = d[i+len]; ans+= abs(d[n-K+i]-lst);//加上右侧弃选后增加的答案 ans-= abs(d[i]-lst);//减去左侧选后减少的答案 if(nX != lst){//如果中位数有变化,则 0 值线升高,要处理面积变化。 ans-=(1ll*((n-K+i)-ed[id[lst+del]]) * (nX-lst)); ans+=(1ll*(nX-lst)*(ed[id[lst+del]] - i)); lst = nX; } ret = min(ret, ans);//答案取最小的 } printf("%lld\n", ret); return 0; }
T2 network (专业网络)
贪心,是某次的作业题。考虑按
代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 2e5+100; inline int read(){ int x = 0;char ch = getchar(); while(ch<'0' || ch>'9') ch = getchar(); while(ch>='0'&&ch<='9') x = x*10+ch-48, ch = getchar(); return x; } struct node{ int a, b; bool operator < (const node &y) const{ return b > y.b; } }p[N]; bool cmp(node x, node y){ if(x.a == y.a){ return x.b < y.b; } return x.a > y.a; } priority_queue<node> q; int n; int main(){ // freopen("network.in", "r", stdin); // freopen("network.out", "w", stdout); n = read(); for(int i = 1; i<=n; ++i){ p[i] = (node){read(), read()}; } sort(p+1, p+n+1, cmp); ll ans = 0, now = 0; for(int i = 1; i<=n; ++i){ q.push(p[i]); while(!q.empty() && n-i+now < p[i].a){ ans+=q.top().b; q.pop(); ++now; } } printf("%lld\n", ans); return 0; }
T3 kangaroo
某天随机随到的题,看到有意思,而且思路新奇就做了,没想到后面这种题还挺多,更没想到今天还做到了……
具体见这篇博客
T4 korale
场上没时间做了 /kk
第一问参考超级钢琴做法,只有一个较小的贡献去掉后才加入较大的贡献,以保证枚举的连续性。
第二问考虑爆搜搜索。用线段树维护一个区间最靠左的最小值,尝试拿这个来组成答案,以保证字典序最小。
代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 1e6+100; inline int read(){ int x = 0; char ch = getchar(); while(ch<'0' || ch>'9') ch = getchar(); while(ch>='0'&&ch<='9') x = x*10+ch-48, ch = getchar(); return x; } int a[N], b[N]; int n, K; struct Segment_Tree{ int tree[N<<2]; #define ls tr<<1 #define rs tr<<1 | 1 void build(int tr, int L, int R){ if(L == R){ return tree[tr] = a[L], void(); } int mid = (L+R) >> 1; build(ls, L, mid); build(rs, mid+1, R); tree[tr] = min(tree[ls], tree[rs]); } int query(int tr, int L, int R, int lq, int rq, ll val){ if (tree[tr] > val) return 0 ; if(lq <= L && R <= rq){ if(tree[tr] > val) return 0; if(L == R) return L; } int mid = (L+R) >> 1, pos; if(lq <=mid){ pos = query(ls, L, mid, lq, rq, val); if(pos) return pos; } return query(rs, mid+1, R, lq, rq, val); } }segt; ll ans = 0, cnt = 1; void write(int x){ if(x >= 10){ write(x/10); } putchar(x%10+48); } int p[N], tot; void dfs(int pos, ll rst){ if(rst == 0){ --cnt; if(!cnt){ printf("%lld\n", ans); for(int i = 1; i<=tot; ++i){ write(p[i]); putchar(' '); } putchar('\n'); exit(0); } } for(int i = pos+1; i<=n; ++i){ i = segt.query(1, 1, n, i, n, rst); if(!i) return; p[++tot] = i; dfs(i, rst-a[i]); --tot; } } struct xwx{ int id; ll sum; bool operator < (const xwx &y) const{ return sum > y.sum; } }; priority_queue<xwx> q; int main(){ n = read(), K = read(); for(int i = 1; i<=n; ++i){ a[i] = b[i] = read(); } sort(b+1, b+n+1); q.push((xwx){1, b[1]}); if(K == 1){ puts("0"); return 0; } for(int i = 2; i<=K; ++i){ xwx tmp = q.top(); if(tmp.sum!=ans){ ans = tmp.sum, cnt = 1; } else{ ++cnt; } q.pop(); if(tmp.id<n){ q.push((xwx){tmp.id+1, tmp.sum-b[tmp.id]+b[tmp.id+1]}); q.push((xwx){tmp.id+1, tmp.sum+b[tmp.id+1]}); } } segt.build(1, 1, n); dfs(0, ans); return 0; }