A. Pens and Pencils (CF 1244 A)
题目大意
给定(a,b,c,d,k),问是否(lceil dfrac{a}{c} ceil + lceil dfrac{b}{d} ceil 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
",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)是楼梯数量,由于(numleq 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,'
');
}
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)。其中(wgeq d)。
解题思路
由于(wgeq d),当(ygeq 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
",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,'
');
for(int i=1;i<=n;++i) printf("%d%c",best_color[i]+1,i==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,'
');
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=sumlimits_{1leq ileq n} max(a_i,b_i)leq k)且最大。
解题思路
我们令(a)递增排列,(s)最小即为(dfrac{n(n+1)}{2}),最大即为((lceilfrac{n}{2} ceil + 1 + n) cdot lfloorfrac{n}{2} floor + n \% 2 cdot lceilfrac{n}{2} ceil),而对于这之间的数,我们发现都可以取到的。一开始(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,'
');
for(int i=1;i<=n;++i) printf("%d%c",i,i==n?'
':' ');
for(int i=1;i<=n;++i) printf("%d%c",p[i],i==n?'
':' ');
return 0;
}