A.
水题。略。
B. (Aborted)
给你一个 \(n*m\) 的矩阵,你可以用 \(1*2\) 的砖铺满矩阵,但要求砖与砖之间不能有公共边或公共点。求最多能放几块砖。
解
看上去只要这样放就可以:
<>.<>.^
......v
<>.<>..
......^
<>.<>.v
但是你有没有考虑过 \(5*6(ans=7)\) :
<>.^.^
...v.v
<>....
...^.^
<>.v.v
\(6*6(ans=8)\) :
<>.^.^
...v.v
<>....
....<>
^.^...
v.v.<>
\(4*4(ans=4)\) :
<>.^
...v
^.<>
v...
事实证明,这道题是没有多项式级别的算法的,然而原题的数据范围是 \(10^9\) ,然后这道题就被删了,这场比赛就变成了unratedstd Wrong Answer
C.
两个长度相等的01字符串 \(s_1,s_2\) ,定义 \(f(s_1,s_2)\) 为 \(s_1[i]≠s_2[i]\) 的 \(i\) 的个数。现给定两个01字符串 \(s,t(|s|>|t|)\) ,求 \(s\) 有多少个长度等于 \(|t|\) 的子串 \(x\) 满足 \(f(x,t)\) 为偶数。 \((|s|,|t|\le 10^6)\)
解
如果 \(s_1\) 包含1的个数和 \(s_2\) 包含1的个数的奇偶性相同,那么 \(f(s_1,s_2)\) 是偶数,否则是奇数。
前缀和处理。时间复杂度 \(O(n)\) 。
D.
给你一个实数序列 \(a\) ,现在要把 \(a\) 中的所有元素向上或向下取整,使得序列之和为0。保证有解。输出一种方案。
解
先让所有元素全部向下取整,然后把不够的加到不是整数的元素上。
本题卡精度,ceil() floor()
请慎用。最好加上一个eps。
E.
将一个给定的01矩阵复制无穷遍得到一个无限大的网络,其中行号+列号为偶数的为原矩阵,为奇数的为原矩阵所有元素取反得到的矩阵,每次询问两个坐标,问两个坐标之间有多少个1。
解
很明显的前缀和+边界特判,但是实在是烦,所以代码就咕了。
F.
有一张图,现在要你删掉若干条边,你只能保留不超过 \(\lceil \frac{n+m}{2} \rceil\) 条边,而且你要保证对于每个节点 \(i\) , \(\lceil \frac{d_i}{2} \rceil \le f_i\) ,其中 \(d_i\) 为操作前节点的度数, \(f_i\) 为操作后节点的度数。 \((1\le n,m\le 10^6)\)
解
对每条边从大到小按 \(\min (f_u-\lceil \frac{d_u}{2} \rceil,f_v-\lceil \frac{d_v}{2} \rceil)\) 排序,然后一波很神奇的操作
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000003;
struct edge{
int from,to;
bool del;
edge():del(0){}
edge(int u,int v):from(u),to(v),del(0){}
}e[maxn];
int n,m,deg[maxn],f[maxn];
int w(int u){
return f[u]-(deg[u]+1)/2;
}
bool operator <(edge x,edge y){
return min(w(x.from),w(x.to))>min(w(y.from),w(y.to));
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
deg[u]++,deg[v]++;
e[i]=edge(u,v);
}
for(int i=1;i<=n;i++)f[i]=deg[i];
sort(e+1,e+m+1);
int k=m,c=m;
while(k>(n+m+1)/2){
int u=e[1].from,v=e[1].to;
f[u]--,f[v]--;
if(w(u)<0||w(v)<0){
f[u]++,f[v]++;
}
else{
k--;
e[1].del=1;
}
swap(e[1],e[c]);
c--;
}
printf("%d\n",k);
for(int i=1;i<=m;i++){
if(!e[i].del){
printf("%d %d\n",e[i].from,e[i].to);
}
}
return 0;
}