A. Pens and Pencils (CF 1244 A)
题目大意
给定\(a,b,c,d,k\),问是否\(\lceil \dfrac{a}{c} \rceil + \lceil \dfrac{b}{d} \rceil \leq k\)?
解题思路
快速读懂题意即可。神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { int kase; read(kase); for (int i = 1; i <= kase; i++) { int a,b,c,d,k; read(a); read(b); read(c); read(d); read(k); int qaq=ceil(a*1.0/c); int qwq=ceil(b*1.0/d); if (qaq+qwq>k) puts("-1"); else printf("%d %d\n",qaq,qwq); } return 0; }
B. Rooms and Staircases (CF 1244 B)
题目大意
两层楼,每层楼有\(n\)个房间,相邻房间之间有门互通,一楼的某些房间与二楼的对应房间有楼梯连接。问从哪里出发,在不重复经过一个房间的情况下,经过的房间数最多。输出这个最多的房间数。
解题思路
如果没有楼梯,答案显然是\(n\),如果有一个楼梯,那么答案就是\(n+1\)或者\(2*s\)或者\(2*(n-s+1)\),\(s\)是楼梯所在的房间编号。很显然答案是在后两者。如果有多个楼梯,由于经过的房间不能再走,那么答案就是\(n+num\)或者\(2*s\)或者\(2*(n-s+1)\),\(num\)是楼梯数量,由于\(num\leq n\),答案还是在后两者,即只用一个楼梯的情况。我们枚举经过的楼梯分别计算答案取最大值即可。神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { int kase; read(kase); for (int i = 1; i <= kase; i++) { int n; read(n); char s[n+1]; scanf("%s",s); int ans=n; for(int i=0;i<n;++i) if (s[i]=='1') ans=max(ans,max(2*(i+1),2*(n-i))); write(ans,'\n'); } return 0; }
C. The Football Season (CF 1244 C)
题目大意
给定\(n,p,w,d\),要求找到一个可行非负整数解\(x,y,z\),满足\(x \cdot w + y \cdot d = p\) 及 \(x + y + z = n\)。其中\(w\geq d\)。
解题思路
由于\(w\geq d\),当\(y\geq w\)有解时,我们不断令\(y=y-w\),\(x=x+d\),直到\(y<w\),这样等式\(x \cdot w + y \cdot d = p\)仍然成立。而由于\(x^{'}+y^{'}=x+d+y-w<x+y\),\(x^{'}+y^{'}\)的和变小,原来有非负数解\(z\)的,此时肯定还有非负数解\(z\),而原来没有的,此时可能会有。故而我们只要枚举\(y\)从\(0\)到\(w-1\)即可。神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { LL n,p,w,d; read(n); read(p); read(w); read(d); LL x=-1,y=-1,z=-1; for(y=0;y<w;++y){ if ((p-y*d)%w==0){ x=(p-y*d)/w; z=n-x-y; break; } } if (x<0||y<0||z<0) puts("-1"); else printf("%lld %lld %lld\n",x,y,z); return 0; }
D. Paint the Tree (CF 1244 D)
题目大意
给树的点染色,有三种颜色。已知每个点的每种颜色的染色费用,求一种染色方案,使得任意相邻的三个点颜色各不相同,且费用最小。不存在该方案输出\(-1\)。
解题思路
我们会发现一个重要性质:存在染色方案的树一定是条链。这样枚举了前两个点的颜色,剩下点的颜色都确定了。一共六种情况扫一遍即可。神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } LL ans=1e16;; void DFS(int n,int fa,int x,int a,int b,int c,LL qwq,vector<int>edge[],LL cost[][3],int cnt[],int color[],int best_color[]){ qwq+=cost[x][a]; color[x]=a; if (x!=fa&&cnt[x]==1){ if (ans>qwq) { ans=qwq; for(int i=1;i<=n;++i) best_color[i]=color[i]; } return; } for(auto i:edge[x]){ if (i==fa) continue; if (b==-1) for(int k=0;k<3;++k){ if (k==a) continue; DFS(n,x,i,k,a,b,qwq,edge,cost,cnt,color,best_color); } else { int k=3-a-b; DFS(n,x,i,k,a,b,qwq,edge,cost,cnt,color,best_color); } } } int main(void) { int n; read(n); LL cost[n+1][3]={0}; for(int i=0;i<3;++i) for (int j=1;j<=n;++j) read(cost[j][i]); int cnt[n+1]={0}; vector<int> edge[n+1]; for(int u,v,i=1;i<n;++i){ read(u); read(v); ++cnt[u]; ++cnt[v]; edge[u].push_back(v); edge[v].push_back(u); } int qwq=0,st=1; int color[n+1]={0},best_color[n+1]={0}; for(int i=1;i<=n;++i){ qwq+=(cnt[i]!=2); if (cnt[i]==1) st=i; } if (qwq!=2) puts("-1"); else{ DFS(n,st,st,0,-1,-1,0,edge,cost,cnt,color,best_color); DFS(n,st,st,1,-1,-1,0,edge,cost,cnt,color,best_color); DFS(n,st,st,2,-1,-1,0,edge,cost,cnt,color,best_color); write(ans,'\n'); for(int i=1;i<=n;++i) printf("%d%c",best_color[i]+1,i==n?'\n':' '); } return 0; }
E. Minimizing Difference (CF 1244 E)
题目大意
给定\(n\)个数,可以进行\(k\)次操作,每次操作选定一个数,使之加一或减一。问最终最大值与最小值的差最小是多少。
解题思路
贪心即可。每次选最大值、最小值数量最小的一个去搞。由于数很大我们离散后就可以数的个数,或者直接拿\(map\)。神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { int n; LL k; read(n); read(k); map<int,LL> qwq; for(int u,i=1;i<=n;++i){ read(u); qwq[u]++; } LL ans=qwq.rbegin()->first-qwq.begin()->first; while(k>0){ if (qwq.size()==1) {ans=0; break;} auto st=qwq.begin(); auto en=qwq.rbegin(); if (st->second<en->second){ auto st_next=st; st_next++; if (((st_next->first-st->first)*st->second)<=k){ ans-=(st_next->first-st->first); k-=((st_next->first-st->first)*st->second); st_next->second+=st->second; qwq.erase(st); } else{ LL qaq=k/st->second; ans-=qaq; k=0; } } else{ auto en_before=qwq.end(); en_before--; en_before--; if (((en->first-en_before->first)*en->second)<=k){ ans-=(en->first-en_before->first); k-=((en->first-en_before->first)*en->second); en_before->second+=en->second; auto ee=qwq.end(); --ee; qwq.erase(ee); } else{ LL qaq=k/en->second; ans-=qaq; k=0; } } } write(ans,'\n'); return 0; }
F. Chips (CF 1244 F)
题目大意
一堆围成圆圈,初始带有黑或白颜色的芯片。有\(k\)个回合,每个回合中,如果一个芯片旁边的两个的芯片都与自己异色,则自己会变成对方的颜色。问\(k\)个回合后每个芯片的颜色。
解题思路
注意到,如果一个芯片旁边有一个芯片颜色与它一样,那么这两个芯片在整个过程中都不会变色,这些芯片我们称之为稳定芯片。在稳定芯片旁边如果有一个不稳定芯片,那么这个不稳定芯片在一个回合后变成与稳定芯片相同颜色后,也不会变色了。那就是说,对于一个圈圈来说,在两个稳定芯片之间都是不稳定的芯片,这个稳定属性会传染,两边每一个回合会传染一个芯片,使之与自己同化。而对于最终还是不稳定的芯片,由于整个过程它都在变色,那看\(k\)是奇是偶即可知道最终的颜色。\(BFS\)模拟传染过程即可。神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int id(int x,int n){ if (x==-1) return n-1; if (x==n) return 0; return x; } char change(char x){ if (x=='W') return 'B'; else return 'W'; } int main(void) { int n,k; read(n); read(k); char s[n+1]; scanf("%s",s); int sign[n]={0}; for(int i=0;i<n;++i) if (s[i]==s[id(i-1,n)]||s[i]==s[id(i+1,n)]) sign[i]=1; queue<pair<pair<int,int>,int>> team; for(int i=0;i<n;++i) { if (sign[i]==1&&sign[id(i+1,n)]==0) team.push(make_pair(make_pair(i,1),0)); if (sign[i]==1&&sign[id(i-1,n)]==0) team.push(make_pair(make_pair(i,-1),0)); } while(!team.empty()){ auto u=team.front(); team.pop(); if (u.second==k) continue; int v=id(u.first.first+u.first.second,n); if (sign[v]==0) { sign[v]=1; s[v]=s[u.first.first]; team.push(make_pair(make_pair(v,u.first.second),u.second+1)); } } bool qwq=k&1; for(int i=0;i<n;++i) if (sign[i]==0&&qwq) putchar(change(s[i])); else putchar(s[i]); return 0; }
G. Running in Pairs (CF 1244 G)
题目大意
有两个\(1\)到\(n\)的排序\(a,b\)。给定\(k\),要求\(s=\sum\limits_{1\leq i\leq n} \max(a_i,b_i)\leq k\)且最大。
解题思路
我们令\(a\)递增排列,\(s\)最小即为\(\dfrac{n(n+1)}{2}\),最大即为\((\lceil\frac{n}{2}\rceil + 1 + n) \cdot \lfloor\frac{n}{2}\rfloor + n \% 2 \cdot \lceil\frac{n}{2}\rceil\),而对于这之间的数,我们发现都可以取到的。一开始\(b\)先递增排列,然后我们任意交换\(b\)中的两个数,假设位置是\(l,r\)那么答案就会增大\(r-l\),然后再对\((l,r)\)内重复操作即可。最极端的情况就变成\(b\)递减排列,即取得了最大值。故贪心即可。神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { int n; LL k; read(n); read(k); k-=(LL)n*(n+1)>>1; if (k<0) {puts("-1"); return 0;} int p[n+1]; for(int i=1;i<=n;++i) p[i]=i; int l=1,r=n; while(k&&l<r){ while(k<r-l) ++l; k-=r-l; swap(p[l],p[r]); if (k>0) ++l,--r; } LL ans=0; for(int i=1;i<=n;++i) ans+=max(i,p[i]); write(ans,'\n'); for(int i=1;i<=n;++i) printf("%d%c",i,i==n?'\n':' '); for(int i=1;i<=n;++i) printf("%d%c",p[i],i==n?'\n':' '); return 0; }
来源:https://www.cnblogs.com/Lanly/p/12258839.html