Educational Codeforces Round 24 题解
来源:互联网 发布:php打印九九乘法表 编辑:程序博客网 时间:2024/06/01 09:03
题目链接:http://codeforces.com/contest/818/problem/A
A:数学,水题。
#include <bits/stdc++.h>using namespace std;typedef long long LL;int main(){ LL n, k; scanf("%lld%lld",&n,&k); LL x = n/(2*(k+1)); if(x == 0){ printf("0 0 %lld\n", n); } else{ printf("%lld %lld %lld\n", x, k*x, n-(k+1)*x); }}
B,水题,模拟。题意:给出一个排列a1…an,进行m轮游戏,首先选定一个leader作为l[1],l[i+1]=a[l[i]]+l[i] a[l[i]]+l[i]=l[i+1] 所以 a[l[i]]=l[i+1]-l[i] 如果遇到有冲突的情况特判一下输出-1(一个以上的位置是同一个数或同一个位置几次得到的结果不一样)
#include <bits/stdc++.h>using namespace std;int n, m, l[110], a[110], ans[110], temp[110];int vis[110];int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=m; i++) scanf("%d",&l[i]); bool flag = 0; for(int i=1; i<=n; i++){ int st = l[1]; memset(vis, 0, sizeof(vis)); memset(temp, 0, sizeof(temp)); int pos = 1; temp[1] = i; vis[i] = 1; bool ok = 1; for(int j=2; j<=m; j++){ if(temp[st]==0){ int x = l[j]-l[j-1]; if(x<=0) x+=n; if(x>n) x-=n; temp[st]=x; ++vis[x]; st = l[j]; } else{ int x = temp[st]+st; if(x>n) x-=n; if(x==l[j]){ st = l[j]; } else{ ok = 0; } } } for(int j=1; j<=n; j++){ if(vis[j]>1){ ok = 0; break; } } if(ok){ for(int j=1; j<=n; j++){ if(temp[j]) ans[j] = temp[j]; else{ for(int k=1; k<=n; k++){ if(!vis[k]){ ans[j] = k; vis[k] = 1; break; } } } } flag = 1; break; } } if(flag==0){ puts("-1"); } else{ for(int i=1; i<=n; i++) printf("%d ", ans[i]); printf("\n"); } return 0;}
C:有d个沙发,每个沙发占据相邻两个格子,定义一个沙发A在另一个沙发B左边为:存在沙发A的格子a和沙发B的格子b使得xa小于xb,求出一个沙发满足给出的cntl,cntr,cntt,cntb m和n都不超过1e5,直接处理出前缀和,O(n)可求
#include <bits/stdc++.h>using namespace std;const int maxn = 100010;struct node{ int x1,y1,x2,y2;}sofa[maxn];int d, n, m, cntl, cntr, cntt, cntb, ans, sum1[maxn], sum2[maxn], sum3[maxn], sum4[maxn];int main(){ scanf("%d%d%d", &d,&n,&m); for(int i=1; i<=d; i++){ scanf("%d%d%d%d", &sofa[i].x1,&sofa[i].y1,&sofa[i].x2,&sofa[i].y2); sum1[min(sofa[i].x1,sofa[i].x2)]++; sum2[max(sofa[i].x1,sofa[i].x2)]++; sum3[min(sofa[i].y1,sofa[i].y2)]++; sum4[max(sofa[i].y1,sofa[i].y2)]++; } scanf("%d%d%d%d", &cntl,&cntr,&cntt,&cntb); for(int i=1; i<=n; i++) sum1[i]+=sum1[i-1]; for(int i=n; i>=1; i--) sum2[i]+=sum2[i+1]; for(int i=1; i<=m; i++) sum3[i]+=sum3[i-1]; for(int i=m; i>=1; i--) sum4[i]+=sum4[i+1]; ans = -1; for(int i=1; i<=d; i++){ int l = sum1[max(sofa[i].x1, sofa[i].x2)-1]; int r = sum2[min(sofa[i].x1, sofa[i].x2)+1]; if(sofa[i].x1 != sofa[i].x2) l--, r--; int t = sum3[max(sofa[i].y1, sofa[i].y2)-1]; int b = sum4[min(sofa[i].y1, sofa[i].y2)+1]; if(sofa[i].y1 != sofa[i].y2) t--,b--; if(l == cntl && r == cntr && t == cntt && b == cntb){ ans = i; break; } } printf("%d\n", ans); return 0;}
D,有n辆车依次驶过,给定对方选择的一个颜色a,请你选择一个颜色b使得在任一时刻cntb>=cnta。
解法:这道题本来O(n)扫一遍就好了,傻逼强行怼了线段树。我的做法就是对所有的颜色开一个线段树,当颜色等于A的时候所有颜色的值-1,不等于A的时候,如果当前颜色所在位置的值>=0的话,给当前值+1,最后查找这个线段树有没有>=0的节点,有的话输出这个值就好了。
#include <bits/stdc++.h>using namespace std;const int maxn = 1e6+7;int n, A, c[maxn];struct node{ int l,r,len,sum; int lazy;}tree[maxn*4];void pushup(int rt){ tree[rt].sum = tree[rt*2].sum+tree[rt*2+1].sum;}void pushdown(int rt){ if(tree[rt].lazy){ tree[rt*2].lazy+=tree[rt].lazy; tree[rt*2+1].lazy+=tree[rt].lazy; tree[rt*2].sum += tree[rt*2].len*tree[rt].lazy; tree[rt*2+1].sum += tree[rt*2+1].len*tree[rt].lazy; tree[rt].lazy = 0; }}void Build(int l, int r, int rt){ tree[rt].l = l, tree[rt].r = r, tree[rt].sum = 0, tree[rt].lazy = 0, tree[rt].len = r-l+1; if(l == r){ return; } int mid = (l+r)/2; Build(l,mid,rt*2); Build(mid+1,r,rt*2+1); pushup(rt);}void update(int L, int R, int c, int rt){ if(L<=tree[rt].l&&tree[rt].r<=R){ tree[rt].sum += c*(tree[rt].len); tree[rt].lazy += c; return; } pushdown(rt); int mid = (tree[rt].l+tree[rt].r)/2; if(R<=mid) update(L,R,c,rt*2); else if(L>mid) update(L,R,c,rt*2+1); else{ update(L,mid,c,rt*2); update(mid+1,R,c,rt*2+1); } pushup(rt);}int query(int L, int R, int rt){ if(L<=tree[rt].l&&tree[rt].r<=R){ return tree[rt].sum; } pushdown(rt); int mid = (tree[rt].l+tree[rt].r)/2; if(R<=mid) return query(L,R,rt*2); else if(L>mid) return query(L,R,rt*2+1); else return query(L,mid,rt*2)+query(mid+1,R,rt*2+1);}int main(){ scanf("%d%d",&n,&A); for(int i=1; i<=n; i++) scanf("%d", &c[i]); Build(1,1000000,1); int ans = -1; for(int i=1; i<=n; i++){ if(c[i]==A){ update(1,1000000,-1,1); } else{ if(query(c[i],c[i],1)>=0){ update(c[i],c[i],1,1); } } } for(int i=1; i<=1000000; i++){ if(i==A) continue; if(query(i,i,1)>=0){ ans = i; break; } } printf("%d\n", ans); return 0;}
E,有多少连续的ai…aj的乘积是k的倍数
解法:将k分解质因数,处理出序列每个质因数个数的前缀和,对于每个左端点通过二分来得到最小的能使乘积为k的倍数的右端点
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int maxn = 400010;LL n, k;LL a[maxn];LL num1[20], num2[20], cnt=0;LL sum[maxn][20];bool check(LL x, LL y){ for(int i=0; i<cnt; i++){ LL temp = sum[y][i]-sum[x-1][i]; if(temp<num2[i]) return false; } return true;}int main(){ scanf("%lld%lld", &n,&k); LL x = k; for(LL i=2; i*i<=x; i++){ if(x%i==0){ int p = 0; num1[cnt++] = i; while(x%i==0){ x/=i; p++; } num2[cnt-1] = p; } } if(x > 1){ num1[cnt++] = x; num2[cnt-1] = 1; } memset(sum, 0, sizeof(sum)); for(LL i=1; i<=n; i++){ scanf("%lld", &a[i]); for(int k = 0; k < cnt; k++){ sum[i][k] = sum[i-1][k]; while(a[i]%num1[k]==0){ sum[i][k]++; a[i]/=num1[k]; } } } LL anss = 0; for(LL i=1; i<=n; i++){ LL l = i, r = n, ans = n; while(l<=r){ LL mid = (l+r)/2; if(check(i, mid)) ans = mid, r=mid-1; else l = mid+1; } if(check(i, ans)) anss = anss+n-ans+1; } printf("%lld\n", anss); return 0;}
F,n个点的图,桥的个数要求不小于边数的一半,问边数的最大值
解法:n个点中k个点两两相连有k*(k-1)/2条边,其余的点顺次相连为桥n-k条边,当k*(k-1)/2<=n-k时才符合要求 可以发现f(k)=n-k+min(n-k,k*(k-1)/2)是一个单峰函数,于是三分得到答案
#include <bits/stdc++.h>using namespace std;typedef long long LL;int q;LL n, ans;LL check(LL mid){ return n-mid+min(n-mid,(mid-1)*mid/2);}int main(){ scanf("%d", &q); while(q--){ scanf("%lld", &n); LL l = 1, r = n; while(l + 1 < r){ LL mid = (l+r)/2; LL midd = (mid+r)/2; if(check(mid)<check(midd)) l = mid; else r = midd; } printf("%lld\n", max(check(l),check(l+1))); }}
G,没读
- Educational Codeforces Round 24 题解
- Educational Codeforces Round 7 题解
- Educational Codeforces Round 7 题解
- Educational Codeforces Round 14 题解
- Educational Codeforces Round 20题解
- Educational Codeforces Round 23 题解
- Educational Codeforces Round 22 题解
- Educational Codeforces Round 25 题解
- Educational Codeforces Round 21 题解
- Educational Codeforces Round 29 题解
- Educational Codeforces Round 19 题解
- Educational Codeforces Round 28 题解
- Educational Codeforces Round 31 题解
- Educational Codeforces Round 32[题解]
- Educational Codeforces Round 30 题解
- Educational Codeforces Round 32 题解
- Educational Codeforces Round 17 题解
- Educational Codeforces Round 34 题解
- Surf描述子形成步骤
- 自定义控件总结1(Android开发艺术探索)
- python3-经纬度的相关计算
- 关于Http_build_query的用法
- 实时获取EditText的值并弹出提示
- Educational Codeforces Round 24 题解
- Oracle、Mysql、Hive多行转一列函数实现及异同
- 欢迎使用CSDN-markdown编辑器
- appkey使用时提示SHA1不一致(签名、SHA1、appkey)
- 将文件间的编译依存关系降至最低
- JAVA数据结构之线性表的链式存储结构——双向链表
- iOS 封装SDK
- Android VectorDrawable 的使用
- 你会为 AI 转型么?我在考虑。。。