Codeforces 1186

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\) ,然后这道题就被删了,这场比赛就变成了unrated
std 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;
}

转载于:https://www.cnblogs.com/BlogOfchc1234567890/p/11109249.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值