【前言】这场比赛是昨天的训练赛,弱队最终做了4题,好像去年是铜牌滚粗。,太弱啦。现在写一下部分题解。
【A Xiongnu's Land 】 http://7xjob4.com1.z0.glb.clouddn.com/3e76f5f069daf5f6fa79969c155e4e14
【题意】WQ和HQB两个人立了攻,汉武帝要把一块沙漠(这片沙漠是有绿洲存在的)赏给这两个人,这片沙漠是正方形的方式存在的,并且给出了举行右上角的坐标(L,L),而且给出了n个绿洲的坐标,面积,现在汉武帝要用一根线把这片地划分成两个部分,使得左边的绿洲面积要大于等于右边的,并且他们之间的差距尽可能的小。询问这根线的位置,保证正整数。
【解题方法】比较水的题目了,想想就知道要维护一个前缀和的前缀和,这题就做完啦。
【AC 代码】
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define LL long long
const int N =2e6;
LL pre[N];
int main()
{
int T,left,top,w,h,R,n;
LL sums;
scanf("%d",&T);
while(T--){
memset(pre,0,sizeof(pre));
scanf("%d%d",&R,&n);
sums=0;
for(int i=0;i<n;i++){
scanf("%d%d%d%d",&left,&top,&w,&h);
w=min(w,R-left);
h=min(h,top);
pre[left+1]+=h;
pre[left+w+1]-=h;
//sum[left+w+1]-=1ll*w*h;
sums+=1ll*w*h;
}
for(int i=1;i<=R;i++){
pre[i]+=pre[i-1];
}
for(int i=1;i<=R;i++){
pre[i]+=pre[i-1];
}
int ans=0;
LL minn=0x3f3f3f3f;
for(int i=1;i<=R;i++){
if(pre[i]>=(sums-pre[i])&&pre[i]-(sums-pre[i])<=minn){
ans=i;
minn=pre[i]-(sums-pre[i]);
}
}
printf("%d\n",ans);
}
return 0;
}
【Today Is a Rainy Day 赛后补题】 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5275
【题意】给了2个数字串a和数字串b,并且这些串里最多有1-6这6个数字,现在有两种操作,一种是把串里的某一个数字全部变成另外一个数字,另一种操作是把串里某一个位置上的数字变成另一个数字,问把b串通过这两个操作变成a串最少需要多少步?
【解题方法】只要想到,全部变比一个变肯定来得优,然后我们需处理代价这题就可以做出来了。后面的代价可以直接算嘛,然后维护最小代价就好啦。
【AC 代码】
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 50005;
const int inf = 0x3f3f3f3f;
int dp[maxn];
int getid1(int *c){
int ret = 0;
for(int i=0; i<6; i++){
ret = ret * 6 + c[i];
}
return ret;
}
void getid2(int s,int *c)
{
for(int i=5; i>=0; i--){
c[i] = s%6;
s /= 6;
}
}
void presolve()
{
int c[10],t[10];
for(int i=0; i<6; i++) c[i] = i;
int s = getid1(c);
memset(dp,inf,sizeof(dp));
dp[s] = 0;
queue<int>que;
que.push(s);
while(que.size())
{
s = que.front();
que.pop();
getid2(s,c);
for(int i=0; i<6; i++){
for(int j=0; j<6; j++){
memcpy(t,c,sizeof(t));
for(int k=0; k<6; k++) if(t[k]==i) t[k]=j;
int v = getid1(t);
if(dp[v]>dp[s]+1){
dp[v]=dp[s]+1;
que.push(v);
}
}
}
}
}
int cnt1[10],cnt2[10][10];
char a[120],b[120];
int main()
{
presolve();
while(scanf("%s",a)!=EOF)
{
scanf("%s",b);
int len =strlen(a);
memset(cnt1,0,sizeof(cnt1));
memset(cnt2,0,sizeof(cnt2));
for(int i=0; i<len; i++){
cnt1[b[i]-'1']++;
cnt2[b[i]-'1'][a[i]-'1']++;
}
int ans = inf;
int t[10];
for(int s=0; s<maxn; s++){
getid2(s,t);
int now = dp[s];
for(int i=0; i<6; i++){
now += cnt1[i] - cnt2[i][t[i]];
}
ans = min(ans,now);
}
printf("%d\n",ans);
}
return 0;
}
【G Mysterious Antiques in Sackler Museum】 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5279
【题意】给4个矩形的宽和高,问能否选出3个拼成一个大矩形
【解题方法】简单模拟,不要漏情况就好,这题队友写的,很稳。
【AC 代码】
#include<cstdio>
using namespace std;
struct node
{
int h,w;
}a[4];
int isok()
{
for(int i=0;i<4;i++){
int flag=0;
for(int j=0;j<4;j++){
if(j==i) continue;
if(a[j].h==a[0].h||a[j].w==a[0].h) continue;
else flag=1;
}
if(flag==0) return 1;
flag=0;
for(int j=0;j<4;j++){
if(j==i) continue;
if(a[j].w==a[0].w||a[j].h==a[0].w) continue;
else flag=1;
}
if(flag==0) return 1;
}
return 0;
}
int check()
{
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
int t1=-1,t2=-1;
if(i==j) continue;
for(int k=0;k<4;k++){
if(k==j||k==i) continue;
if(t1==-1){
t1=k;
for(int x=0;x<4;x++){
if(x==j||x==t1||x==i) continue;
t2=x;
}
break;
}
}
if(a[t1].h==a[t2].w&&(a[t1].w+a[t2].h==a[j].h||a[t1].w+a[t2].h==a[j].w)) return 1;
if(a[t1].h==a[t2].h&&(a[t1].w+a[t2].w==a[j].h||a[t1].w+a[t2].w==a[j].w)) return 1;
if(a[t1].w==a[t2].w&&(a[t1].h+a[t2].h==a[j].h||a[t1].h+a[t2].h==a[j].w)) return 1;
if(a[t1].w==a[t2].h&&(a[t1].h+a[t2].w==a[j].h||a[t1].h+a[t2].w==a[j].w)) return 1;
}
}
return 0;
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d%d%d%d%d%d%d",&a[0].h,&a[0].w,&a[1].h,&a[1].w,&a[2].h,&a[2].w,&a[3].h,&a[3].w);
if(isok()) printf("Yes\n");
else if(check()) printf("Yes\n");
else printf("No\n");
}
return 0;
}
【I Snake Carpet 】https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5281
【题意】给一个数n,然后现在对于1-n的每一个数i,你都可以用这i个相同的数字i构成一条长度为i的蛇,要满足一个条件,就是>2的偶数的转弯必须是偶数,奇数必须是奇数。
【解题方法】队友在纸上画了一下,感觉是蛇形填数,乱扒了几组样例,感觉还是挺妥的,就开始敲了,不过这题我们debug了很久,中间下标什么很烦,orz。
【AC 代码】
#include <cstdio>
#include <algorithm>
using namespace std;
struct node
{
int x,y;
};
node ans[1000][1000];
int numm[1000];
void f(int n,int x,int y)
{
if(n<=0) return ;
if(n==1){
printf("%d %d\n",x,y);
return ;
}
if(n%2==0){
f(n-1,x,y+2);
int i=x,j=y,k,flag=0;
for(k=0;k<n/2;k++,i--){
if(flag==0) printf("%d %d",i,j),flag=1;
else printf(" %d %d",i,j);
}
i++;
for(k=0,j++;k<n/2;k++,i++){
if(flag==0) printf("%d %d",i,j),flag=1;
else printf(" %d %d",i,j);
}
printf("\n");
}
else if(n>=3){
f(n-3,x,y+2);
int i=x,j=y,k,cnt=0,num;
num=0;
for(k=0;k<(n+1)/2;k++,i--) ans[cnt][num++]=(node){i,j};
i++;
for(k=0,j++;k<n/2;k++,j++) ans[cnt][num++]=(node){i,j};
numm[cnt++]=num;
j--;
num=0;
for(k=0,j++;k<(n-1)/2;k++,j++) ans[cnt][num++]=(node){i,j};
j--;
for(i++,k=0;k<(n-1)/2;k++,j--) ans[cnt][num++]=(node){i,j};
numm[cnt++]=num;
j++;
num=0;
for(k=0,j--;k<(n-2)/2+1;k++,j--) ans[cnt][num++]=(node){i,j};
j++;
for(k=0,i++;k<(n-2)/2;k++,i++) ans[cnt][num++]=(node){i,j};
numm[cnt++]=num;
for(int i=cnt-1;i>=0;i--){
for(int j=0;j<numm[i];j++){
if(j==0) printf("%d %d",ans[i][j].x,ans[i][j].y);
else printf(" %d %d",ans[i][j].x,ans[i][j].y);
}
printf("\n");
}
}
}
int main()
{
int n;
while(~scanf("%d",&n)){
if(n%2==0) printf("%d %d\n",n/2,n+1);
else printf("%d %d\n",(n+1)/2,n);
if(n%2==0) f(n,n/2,1);
else f(n,(n+1)/2,1);
}
return 0;
}
【 J - Osu! Master】 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5282
【题意】不是太懂,我直接看样例,猜了个结论秒过,我的结论就是连续上升的数字或者s的和。
【解题方法】如上。
【AC 代码】
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n;
int main()
{
while(scanf("%d",&n)!=EOF)
{
int x;
char op[3];
int ans=0;
int last=-1;
for(int i=0; i<n; i++){
scanf("%s",op);
if(op[0]=='S'){
ans++;
last=-1;
}else{
scanf("%d",&x);
if(x>last&&last!=-1){
last=x;
continue;
}else{
ans++;
last=x;
}
}
}
printf("%d\n",ans);
}
return 0;
}