博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
codeforces Educational Codeforces Round 24 (A~F)
阅读量:5124 次
发布时间:2019-06-13

本文共 8910 字,大约阅读时间需要 29 分钟。

题目链接:

A. Diplomas and Certificates

 

题解:水题

#include 
#include
#include
using namespace std;typedef long long ll;int main() { ll n , k; cin >> n >> k; ll gg = n / 2; if(gg < (k + 1)) cout << 0 << ' ' << 0 << ' ' << n << endl; else { cout << gg / (k + 1) << ' ' << gg / (k + 1) * k << ' ' << n - gg / (k + 1) - gg / (k + 1) * k << endl; } return 0;}

 

B. Permutation Game(构造)

 

题解:也是一道水题模拟构造一下就行了

if l[i + 1] > l[i] a[l[i]] = l[i + 1] - l[i];
else    a[l[i]] = l[i + 1] - l[i] + n

最后没有被赋值的点敷一下值就行。

#include 
using namespace std;int l[200] , a[200] , vis[200];int main() { int n , m; cin >> n >> m; int flag = 0; for(int i = 1 ; i <= m ; i++) cin >> l[i]; for(int i = 1 ; i <= n ; i++) a[i] = 0; for(int i = 1 ; i < m ; i++) { if(l[i + 1] > l[i]) { if(a[l[i]]) { if(a[l[i]] != l[i + 1] - l[i]) { flag = 1; break; } } a[l[i]] = l[i + 1] - l[i]; } else { if(a[l[i]]) { if(a[l[i]] != l[i + 1] - l[i] + n) { flag = 1; break; } } a[l[i]] = l[i + 1] - l[i] + n; } } for(int i = 1 ; i <= n ; i++) { vis[a[i]]++; if(!a[i]) continue; if(vis[a[i]] > 1) { flag = 1; break; } } int cnt = 1; for(int i = 1 ; i <= n ; i++) { if(a[i] == 0) { while(vis[cnt] != 0) cnt++; a[i] = cnt; vis[a[i]] = 1; } } for(int i = 1 ; i <= n ; i++) if(!a[i]) {flag = 1; break;} if(flag) cout << -1 << endl; else { for(int i = 1 ; i <= n ; i++) cout << a[i] << ' '; cout << endl; } return 0;}

 

C. Sofa Thief

 

题解:稍微有点麻烦的题目,主要还是求一下前缀,由于一个沙发占两格所以处理起来可能有点麻烦具体看一下代码最终还是要求前缀来解决这个问题。

#include 
#include
using namespace std;const int M = 1e5 + 10;struct TnT { int x1 , y1 , x2 , y2 , id;}T[M];int l[M] , r[M] , t[M] , b[M];int sum[M];int main() { int d; cin >> d; int n , m; cin >> n >> m; for(int i = 1 ; i <= d ; i++) { cin >> T[i].x1 >> T[i].y1 >> T[i].x2 >> T[i].y2 , T[i].id = i; } int cntl , cntr , cntt , cntb; cin >> cntl >> cntr >> cntt >> cntb; memset(sum , 0 , sizeof(sum)); for(int i = 1 ; i <= d ; i++) { sum[min(T[i].x1 , T[i].x2)]++; } for(int i = 1 ; i <= n ; i++) { sum[i] += sum[i - 1]; } for(int i = 1 ; i <= d ; i++) { if(T[i].x1 != T[i].x2) l[i] = sum[min(T[i].x1 , T[i].x2)] - 1; else l[i] = sum[T[i].x1 - 1]; } memset(sum , 0 , sizeof(sum)); for(int i = 1 ; i <= d ; i++) { sum[max(T[i].x1 , T[i].x2)]++; } for(int i = n ; i >= 1 ; i--) { sum[i] += sum[i + 1]; } for(int i = 1 ; i <= d ; i++) { if(T[i].x1 != T[i].x2) r[i] = sum[max(T[i].x1 , T[i].x2)] - 1; else r[i] = sum[T[i].x1 + 1]; } memset(sum , 0 , sizeof(sum)); for(int i = 1 ; i <= d ; i++) { sum[min(T[i].y1 , T[i].y2)]++; } for(int i = 1 ; i <= m ; i++) { sum[i] += sum[i - 1]; } for(int i = 1 ; i <= d ; i++) { if(T[i].y1 != T[i].y2) t[i] = sum[min(T[i].y1 , T[i].y2)] - 1; else t[i] = sum[T[i].y1 - 1]; } memset(sum , 0 , sizeof(sum)); for(int i = 1 ; i <= d ; i++) { sum[max(T[i].y1 , T[i].y2)]++; } for(int i = m ; i >= 1 ; i--) { sum[i] += sum[i + 1]; } for(int i = 1 ; i <= d ; i++) { if(T[i].y1 != T[i].y2) b[i] = sum[max(T[i].y1 , T[i].y2)] - 1; else b[i] = sum[T[i].y1 + 1]; } int flag = 0; for(int i = 1 ; i <= d ; i++) { //cout << l[i] << ' ' << r[i] << ' ' << t[i] << ' ' << b[i] << endl; if(cntl == l[i] && cntr == r[i] && cntt == t[i] && cntb == b[i]) { flag = 1; cout << i << endl; break; } } if(!flag) cout << -1 << endl; return 0;}

 

D. Multicolored Cars (优先队列)

 

题解:可用优先队列辅助一下具体看一下代码挺好理解的。一旦出现出现次数最小的颜色小于A直接pop出去。

#include 
#include
#include
using namespace std;const int M = 1e6 + 10;int cnt[M] , vis[M];struct TnT { int num; TnT() {} TnT(int num):num(num) {} bool operator <(const TnT &a) const { return cnt[num] > cnt[a.num]; }};priority_queue
q;int main() { int n , A; scanf("%d%d" , &n , &A); int count = 0 , flag = 1; memset(vis , 0 , sizeof(vis)); for(int i = 1 ; i <= n ; i++) { int c; scanf("%d" , &c); if(c == A) count++; else { cnt[c]++; if(cnt[c] > count && !vis[c]) q.push(c) , vis[c] = 1; else vis[c] = 1; } while(!q.empty()) { TnT gg = q.top(); if(cnt[gg.num] >= count) break; q.pop(); } if(q.empty()) flag = 0; } if(!flag) printf("-1\n"); else { if(q.empty()) printf("-1\n"); else printf("%d\n" , q.top().num); } return 0;}

 

E. Card Game Again(思维+二分)

 

题解:现将k因式分解然后拿因式的和求前缀显然是递增的然后遍历一遍向前二分

#include 
#include
using namespace std;const int M = 1e5 + 10;typedef long long ll;ll gcd(ll a , ll b) { return (b <= 0) ? a : gcd(b , a % b);}struct dig { ll num; int sum;};struct TnT { int Size; dig a[64]; TnT():Size(0) { memset(a , 0 , sizeof(a)); } TnT operator +=(const TnT &b) { for(int i = 0 ; i < 64 ; i++) { a[i].sum += b.a[i].sum; } return (*this); } TnT operator -(const TnT &b) { for(int i = 0 ; i < 64 ; i++) { a[i].sum -= b.a[i].sum; } return (*this); }}s , pre[M];void getTnT(ll x , TnT &gg) { gg.a[gg.Size].num = 1 , gg.a[gg.Size].sum++; gg.Size++; ll i; for(i = 2 ; i * i <= x ; i++) { if(x % i == 0) { gg.a[gg.Size].num = i; while(!(x % i)) x /= i , gg.a[gg.Size].sum++; gg.Size++; } } if(x >= i) gg.a[gg.Size].num = x , gg.a[gg.Size].sum++ , gg.Size++;}void getTnT_arr(ll x , TnT &gg) { int len = s.Size; gg.a[0].num = 1 , gg.a[0].sum++; for(int i = 1 ; i < len ; i++) { if(x % s.a[i].num == 0) { gg.a[i].num = s.a[i].num; while(!(x % s.a[i].num)) x /= s.a[i].num , gg.a[i].sum++; } else gg.a[i].num = s.a[i].num , gg.a[i].sum = 0; } gg.Size = len;}ll arr[M];int cau(int pos , int ed) { TnT gl = pre[ed]; TnT gg = gl - pre[pos - 1]; int flag = 0; for(int i = 0 ; i < s.Size ; i++) { if(gg.a[i].sum < s.a[i].sum) { flag = 1; break; } } return flag;}int binsearch(int l , int r , int ed) { int mid = (l + r) >> 1; int ans = 0; while(l <= r) { mid = (l + r) >> 1; if(cau(mid , ed)) r = mid - 1; else { ans = mid; l = mid + 1; } } return ans;}int main() { int n; ll k; scanf("%d%lld" , &n , &k); getTnT(k , s); pre[0].Size = s.Size; for(int i = 1 ; i <= n ; i++) { scanf("%lld" , &arr[i]); arr[i] = gcd(arr[i] , k); getTnT_arr(arr[i] , pre[i]); pre[i] += pre[i - 1]; } ll ans = 0; for(int i = 1 ; i <= n ; i++) { int pos = binsearch(1 , i , i); ans += pos; } printf("%lld\n" , ans); return 0;}

 

F. Level Generation(三分)

 

题解:主要还是推一下公式一共有n个点,有k个点是任意联通的那么显然有n-k个点是单连通的那么n-k个单连通的点贡献的边数是(n-k)条边。k个点最多能连接的边的个数是min(n-k(由于要求桥的个数要超过总边数的一半),k*(k-1)/2(k个点最多能连接的边的个数)),这个自行理解一下。然后我们可以发现边的贡献是

n-k+min(n-k,k*(k-1)/2)。像这种有单峰或单谷的函数可以利用三分来求最值

#include 
#include
#include
using namespace std;typedef long long ll;ll n;bool cau(ll k) { if(k * (k - 1) / 2 > n - k) return true; else return false;}ll ternsearch(ll l , ll r) { ll mid = (l + r) >> 1; ll sum = 0; if(cau(mid)) sum = 2 * n - 2 * mid; else sum = n - mid + mid * (mid - 1) / 2; while(l <= r) { mid = (l + r) >> 1; ll midl = (l + mid) >> 1; ll midr = (r + mid) >> 1; ll now = 0 , sum1 = 0 , sum2 = 0; if(cau(mid)) now = 2 * n - 2 * mid; else now = n - mid + mid * (mid - 1) / 2; sum = max(sum , now); if(cau(midl)) sum1 = 2 * n - 2 * midl; else sum1 = n - midl + midl * (midl - 1) / 2; sum = max(sum1 , sum); if(cau(midr)) now = 2 * n - 2 * midr; else now = n - midr + midr * (midr - 1) / 2; sum = max(sum2 , sum); if(cau(midl) && cau(midr)) r = mid - 1; else if(!cau(midl) && !cau(midr)) l = mid + 1; else { if(sum1 < sum2) r = midr - 1; else l = midl + 1; } } return sum;}int main() { int q; scanf("%d" , &q); while(q--) { scanf("%lld" , &n); printf("%lld\n" , ternsearch(1 , n)); } return 0;}

转载于:https://www.cnblogs.com/TnT2333333/p/7132353.html

你可能感兴趣的文章
HTML元素定义 ID,Class,Style的优先级
查看>>
构造者模式
查看>>
http和https的区别
查看>>
Hbuild在线云ios打包失败,提示BuildConfigure Failed 31013 App Store 图标 未找到 解决方法...
查看>>
找到树中指定id的所有父节点
查看>>
今天新开通了博客
查看>>
AS3优化性能笔记二
查看>>
ElasticSearch(站内搜索)
查看>>
4----COM:a Generative Model for group recommendation(组推荐的一种生成模型)
查看>>
UVA 11137 - Ingenuous Cubrency
查看>>
js阻止事件冒泡的两种方法
查看>>
Java异常抛出
查看>>
[SQL Server 系] T-SQL数据库的创建与修改
查看>>
74HC164应用
查看>>
变量声明和定义的关系
查看>>
Wpf 之Canvas介绍
查看>>
linux history
查看>>
jQuery on(),live(),trigger()
查看>>
Python2.7 urlparse
查看>>
sencha touch在华为emotion ui 2.0自带浏览器中圆角溢出的bug
查看>>