Codeforces Round #552 (Div. 3)
休闲VP发现打的真的太休闲了,完全没有比赛的氛围
A,B
不管
C
暴力跑第一轮和最后一轮
中间的轮数直接做除法
#include<cstdio> #include<iostream> #include<queue> #include<algorithm> #include<cstring> #include<cctype> #include<vector> #include<ctime> #include<cmath> #define LL long long #define pii pair<int,int> #define mk make_pair #define fi first #define se second using namespace std; inline int read(){ int v = 0,c = 1;char ch = getchar(); while(!isdigit(ch)){ if(ch == '-') c = -1; ch = getchar(); } while(isdigit(ch)){ v = v * 10 + ch - 48; ch = getchar(); } return v * c; } LL aaa,bbb,ccc; LL ans; int aa[5],bb[5],cc[5]; inline LL work(LL x,LL a,LL b,LL c){ for(int j = x;j <= 7;++j){ if(j == 1 || j == 4 || j == 7) a--; if(j == 2 || j == 6) b--; if(j == 3 || j == 5) c--; if(a < 0 || b < 0 || c < 0) return j - x; } LL week,day; LL resta = a / 3; LL restb = b / 2; LL restc = c / 2; week = min(resta,min(restb,restc)); LL ans = week * 7 + 7 - x + 1; a = a - week * 3,b -= week * 2,c -= week * 2; for(int j = 1;j <= 7;++j){ if(j == 1 || j == 4 || j == 7) a--; if(j == 2 || j == 6) b--; if(j == 3 || j == 5) c--; ans++; if(a < 0 || b < 0 || c < 0) return ans - 1; } for(int j = 1;j <= 7;++j){ if(j == 1 || j == 4 || j == 7) a--; if(j == 2 || j == 6) b--; if(j == 3 || j == 5) c--; ans++; if(a < 0 || b < 0 || c < 0) return ans - 1; } } int main(){ cin >> aaa >> bbb >> ccc; aa[1] = 4,aa[2] = 7,aa[3] = 8; bb[1] = 6,bb[2] = 9; cc[1] = 5,cc[2] = 10; for(int i = 1;i <= 7;++i){ ans = max(ans,work(i,aaa,bbb,ccc)); // printf("%d %d\n",i,ans); } cout << ans; return 0; }
D
之前贪心发现贪错了
发现操作分位3种
\(x-1\),\(y - 1\),\(x-1,y+1\)
可以证明当\(s[i] = 1\)时,使用\(x - 1,y+1\)一定不会更劣
所以就尽可能的在\(s[i] = 1\)时使用\(x\)就好了
#include<cstdio> #include<iostream> #include<queue> #include<algorithm> #include<cstring> #include<cctype> #include<vector> #include<ctime> #include<cmath> #define LL long long #define pii pair<int,int> #define mk make_pair #define fi first #define se second using namespace std; const int N = 2e5 + 3; int s[N]; int n,a,b,num;//b:太阳能 inline int read(){ int v = 0,c = 1;char ch = getchar(); while(!isdigit(ch)){ if(ch == '-') c = -1; ch = getchar(); } while(isdigit(ch)){ v = v * 10 + ch - 48; ch = getchar(); } return v * c; } int main(){ n = read(),a = read(),b = read(),num = 0; int rest = b; for(int i = 1;i <= n;++i) s[i] = read(); for(int i = 1;i <= n;++i){ if(a == 0 && rest == 0) {printf("%d\n",i - 1);return 0;} if(s[i] == 0 && rest != 0) rest--; else if(s[i] == 0 && rest == 0) a--; else if(s[i] == 1 && rest != b){ if(a == 0) rest--; else { a--; if(rest != 0) num++; rest++; } } else if(s[i] == 1 && rest == b){ rest--; } // printf("%d %d\n",a,rest); } printf("%d\n",n); return 0; } /* 19 7 4 0 0 1 1 0 1 0 0 1 0 1 1 1 1 1 1 0 0 1 */
E
直接用双向链表模拟就好了
时间复杂度可以证明
暴力删除
懒得写链表,就用set维护
#include<cstdio> #include<iostream> #include<queue> #include<algorithm> #include<cstring> #include<cctype> #include<vector> #include<ctime> #include<set> #include<cmath> #define LL long long #define pii pair<int,int> #define mk make_pair #define fi first #define se second using namespace std; const int N = 2e5 + 3; int a[N]; int L[N]; int R[N]; bool book[N]; int n,k; int ans[N]; set<pii> s; set<int> ss; int sta[N]; int tot; set<pii>::iterator it; set<int>::iterator iit; inline int read(){ int v = 0,c = 1;char ch = getchar(); while(!isdigit(ch)){ if(ch == '-') c = -1; ch = getchar(); } while(isdigit(ch)){ v = v * 10 + ch - 48; ch = getchar(); } return v * c; } int main(){ int now = 1; n = read(),k = read(); for(int i = 1;i <= n;++i) a[i] = read(),s.insert(mk(a[i],i)),ss.insert(i); while(!s.empty()){ it = s.end();it--; pii x = *it; tot = 0; iit = ss.lower_bound(x.se); for(int num = 0;num <= k;--iit,++num){ // printf("%d ",*iit); ans[*iit] = now; s.erase(mk(a[*iit],*iit)); sta[++tot] = *iit; if(iit == ss.begin()) break; } iit = ss.lower_bound(x.se); for(int num = 0;num <= k && iit != ss.end();++iit,++num){ // printf("%d ",*iit); ans[*iit] = now; s.erase(mk(a[*iit],*iit)); sta[++tot] = *iit; } // puts(""); for(int i = 1;i <= tot;++i) ss.erase(sta[i]); if(now == 1) now = 2; else now = 1; } for(int i = 1;i <= n;++i) printf("%d",ans[i]); return 0; }
F
发现\(k\)这么小,肯定有东西
发现购买的物品一定是前\(k\)
前\(k\)小一定是从大往小买
直接排序
所以我们设\(f_i\)表示前\(i\)个物品的最小花费
每次枚举用了哪一个优惠
或者不用优惠就好了
#include<cstdio> #include<iostream> #include<queue> #include<algorithm> #include<cstring> #include<cctype> #include<vector> #include<ctime> #include<cmath> #define LL long long #define pii pair<int,int> #define mk make_pair #define fi first #define se second using namespace std; const int N = 2e5 + 3; inline int read(){ int v = 0,c = 1;char ch = getchar(); while(!isdigit(ch)){ if(ch == '-') c = -1; ch = getchar(); } while(isdigit(ch)){ v = v * 10 + ch - 48; ch = getchar(); } return v * c; } int n,k,m; int bar[N]; int f[N]; int a[N]; int sum[N]; int main(){ n = read(),m = read(),k = read(); for(int i = 1;i <= n;++i) a[i] = read(); for(int i = 1;i <= m;++i){ int x = read(),y = read(); bar[x] = max(bar[x],y); } sort(a + 1,a + n + 1); reverse(a + 1,a + k + 1); for(int i = 1;i <= k;++i) sum[i] = sum[i - 1] + a[i]; memset(f,0x3f,sizeof(f)); f[0] = 0; // for(int i = 1;i <= k;++i) printf("%d\n",a[i]); for(int i = 1;i <= k;++i){ for(int j = 1;j <= i;++j) f[i] = min(f[i],f[i - j] + sum[i] - sum[i - j] - (sum[i] - sum[i - bar[j]])); f[i] = min(f[i],f[i - 1] + a[i]); } cout << f[k] << endl; return 0; }
G
\[ lcm(i,j) = \frac{i\times j}{gcd(i,j)} \]
我们就枚举\(gcd(i,j)\)
显然\(i,j\)都要是他的倍数
在枚举的时候顺带更新答案就好了
CF上开\(4\)s,\(10^7\)一个\(log\)还是可以过得
#include<cstdio> #include<iostream> #include<queue> #include<algorithm> #include<cstring> #include<cctype> #include<vector> #include<ctime> #include<cmath> #define LL long long #define pii pair<int,int> #define mk make_pair #define fi first #define se second using namespace std; const int N = 1e7 + 3; const int M = 1e7; int n; int a[N]; LL ans = 9999999999999999; pii id; int vis[N]; inline int read(){ int v = 0,c = 1;char ch = getchar(); while(!isdigit(ch)){ if(ch == '-') c = -1; ch = getchar(); } while(isdigit(ch)){ v = v * 10 + ch - 48; ch = getchar(); } return v * c; } int main(){ n = read(); for(int i = 1;i <= n;++i){ a[i] = read(); if(vis[a[i]]){ if(a[i] < ans) ans = a[i],id = mk(vis[a[i]],i); } vis[a[i]] = i; } for(int d = 1;d <= M;++d){ int maxx1 = 0,maxx2 = 0; for(int x = d;x <= M;x += d){ if(vis[x]){ if(!maxx1) maxx1 = vis[x]; else if(!maxx2) maxx2 = vis[x]; else maxx2 = maxx1,maxx1 = vis[x]; if(maxx1 != 0 && maxx2 != 0) if(1ll * a[maxx1] * a[maxx2] / d < ans) ans = 1ll * a[maxx1] * a[maxx2] / d,id = mk(maxx1,maxx2); // printf("%d %d %d %lld\n",d,maxx1,maxx2,ans); } } } if(id.fi > id.se) swap(id.fi,id.se); printf("%d %d\n",id.fi,id.se); return 0; }