CodeForces - 1457
A - Prison Break
特判矩形四个顶点
const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
ll t,n,m,r,c;
int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld%lld",&n,&m,&r,&c);
WW(max(r-1,n-r)+max(c-1,m-c));
}
return 0;
}
B - Repainting Street
范围小,所以用暴力解
const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
int t,n,a[maxn],pre[maxn],num[maxn],k;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
rep(i,1,100)pre[i]=0,num[i]=INF;
rep(i,1,n)
{
scanf("%d",&a[i]);
num[a[i]]=0;
}
rep(j,1,100)
{
rep(i,1,n)
{
if (a[i]==j||i<=pre[j])continue;
pre[j]=i+k-1;
num[j]++;
}
}
int ans=INF;rep(i,1,n)ans=min(ans,num[a[i]]);W(ans);
}
return 0;
}
C - Bouncing Ball
O(n)枚举删除头部的元素数量,乘y
O(1)获取需要修改的0的数量,乘x
const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
int t,n,p,k,a[maxn],x,y,num[maxn];
int f(int x,int y)
{
if (x%y==0)return x/y;
else return x/y+1;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&p,&k);
rep(i,1,n)num[i]=0;
rep(i,1,n)
{
scanf("%1d",&a[i]);
if (a[i]&&i>=p)num[i%k]++;
}
scanf("%d%d",&x,&y);
ll ans=INFF;
rep(i,0,n-p)
{
int st=i+p;
ans=min(ans,1ll*i*y+1ll*(f(n-st+1,k)-num[st%k])*x);
if (a[st])num[st%k]--;
}
WW(ans);
}
return 0;
}
D - XOR-gun
对于每个数字,根据其二进制的第一个1分类
例如,0101属于第三类,1000属于第四类
如果同一类中有>=3个数字,就一定能用一次就能找到破坏的方法
例如:
1000
1011
1100
选取任意的两个数字,他们的第一位肯定会被异或成0
回到本题,给出n个递增的数字
如果说有连续的3个数字(假设是x,y,z)都属于同一类
那么将y,z取异或,就一定小于x,满足破坏条件
对于1e9范围内的数字,二进制表示下最多有30位
假设每一类都是小于3个数字的,那么最多只有60位,即max(n)<=60
此时就可以暴力枚举发生a[i]>a[i+1]的这个i位置
const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
ll n,a[maxn],pre[maxn];
int main()
{
scanf("%lld",&n);
rep(i,1,n)scanf("%lld",&a[i]);
rep(i,1,n)pre[i]=pre[i-1]^a[i];
a[n+1]=INFF;
rep(i,2,n)
{
ll tmp=a[i]^a[i-1];
if (a[i-2]>tmp||tmp>a[i+1])
{
W(1);
return 0;
}
}
int ans=INF;
rep(i,1,n-1)
{
int r1=i,l2=i+1;
rep(l1,1,r1)
{
rep(r2,l2,n)
{
ll leftnum=pre[r1]^pre[l1-1];
ll rightnum=pre[r2]^pre[l2-1];
if (leftnum>rightnum)ans=min(ans,r1-l1+r2-l2);
}
}
}
if (ans==INF)W(-1);
else W(ans);
return 0;
}