首页 > 其他分享 >Codeforces Round #824 (Div. 2)

Codeforces Round #824 (Div. 2)

时间:2022-10-05 14:22:05浏览次数:78  
标签:Node return 匹配 int 打乱 Codeforces 824 Div include

题目链接

A ~ D 懒得写。

不是因为题不好,其实我觉得做起来非常舒适。但就是懒得写了(

E - House Planning

\(d_1,d_2\) 全打乱感觉很难。先看看不打乱怎么做。

对于每个 \(i\),我们知道 \(d_{1,i}=|p_1-h_i|\) 和 \(d_{2,i}=|p_2-h_i|\) 。

容易发现 \(x=|p_1-p_2|\) 是个关键的量,它一定与 \(d_{1,i}+d_{2,i}\) 或 \(|d_{1,i}-d_{2,i}|\) 相等。

用 \(i=1\) 找到 \(x\) 的两个可能值,然后用 \(i=2\sim n\) 验证。非常 easy 啊。

回到原题,\(d_1,d_2\) 都是打乱的。

那么 \(d_{1,1}\) 在 \(d_2\) 中对应的元素有 \(n\) 种可能,因此 \(x\) 有 \(2n\) 个可能值。

现在的问题是,对于一个 \(x\) 的可能值,如何进行验证。

赛时想法:二分图匹配大力艹。

然而我甚至已经忘记二分图匹配怎么写了。大寄特寄。

感觉自己很傻逼。

赛后看题解,发现正解做法要简洁得多:

考虑 \(d_1,d_2\) 中最大的元素 \(t\) 。

由于 \(d_1,d_2\) 中没有 \(t+x\) 这个元素,因此 \(t\) 只能匹配到 \(|t-x|\) 。

如果也没有 \(|t-x|\) ,就寄了。否则重复上述步骤,直到所有元素都匹配完。

时间复杂度 \(O(n^2\log n)\) 。

感觉自己非常傻逼。

View Code
#include<stdio.h>
#include<queue>
#include<map>
#define rep(i,l,r) for (int i=l; i<=r; ++i)
 
const int N=1005;
 
int T,n,m,x,f,mn,d1[N],d2[N],p[N];
std::map<int,int>v1,v2;
 
struct Node { int i,x; };
bool operator < (Node p,Node q) { return p.x<q.x; }
std::priority_queue<Node>Q;
 
inline int abs(int x) { return x>0?x:-x; }
inline int min(int x,int y) { return x<y?x:y; }
 
bool check() {
    m=0,v1.clear(),v2.clear();
    while (!Q.empty()) Q.pop();
    rep(i,1,n) {
        ++v1[d1[i]],Q.push({1,d1[i]});
        ++v2[d2[i]],Q.push({2,d2[i]});
    }
    while (!Q.empty()) {
        Node q=Q.top(); Q.pop();
        if (q.i==1) {
            if (!v1[q.x]) continue; --v1[q.x];
            int &t=v2[abs(q.x-x)];
            if (!t) return 0; --t,p[++m]=q.x;
        }
        else {
            if (!v2[q.x]) continue; --v2[q.x];
            int &t=v1[abs(q.x-x)];
            if (!t) return 0; --t,p[++m]=x-q.x;
        }
    }
    return 1;
}
 
int main() {
    scanf("%d",&T);
    while (T--) {
        scanf("%d",&n),f=0;
        rep(i,1,n) scanf("%d",d1+i);
        rep(i,1,n) scanf("%d",d2+i);
        rep(i,1,n) {
            x=d1[1]+d2[i];
            if (check()) { f=1; break; }
            x=abs(d1[1]-d2[i]);
            if (check()) { f=1; break; }
        }
        if (!f) { puts("NO"); continue; }
        puts("YES"),mn=0;
        for (int i=1; i<=n; ++i)
            mn=min(mn,p[i]);
        for (int i=1; i<=n; ++i)
            printf("%d ",p[i]-mn);
        printf("\n%d %d\n",-mn,x-mn);
    }
    return 0;
}

标签:Node,return,匹配,int,打乱,Codeforces,824,Div,include
From: https://www.cnblogs.com/REKonib/p/16754769.html

相关文章

  • Codeforces Round #774 (Div. 2) - E. Power Board
    枚举+数论Problem-E-Codeforces题意有一个\(n*m\;(1<=n,m<=10^6)\)的矩阵,第i行第j列是\(i^j\),求这个矩阵中的\(n*m\)的数中有多少种不同的数思路......
  • Codeforces Round #785 (Div. 2) - D. Lost Arithmetic Progression
    GCDProblem-D-Codeforces题意有2个等差数列A,B,它们公有的项组成新的等差数列C;现在给出B的(首项,公差,项数)=(b,q,y),C的(首项,公差,项数)=(c,r,z)求满足条件的A的数量,如......
  • CodeForces 1527E Partition Game
    洛谷传送门CF传送门考虑朴素dp:设\(f_{i,j}\)表示分了\(j\)段且第\(j\)段的末尾是\(i\)的最小花费。有转移:\(f_{i,j}\gets\min\limits_{k=0}^{i-1}f_{k,j-1......
  • Codeforces Educational Codeforces Round 136 C D
    C一开始没有读懂题意,以为是轮流游戏,看别人翻译才发现先手在下一轮会变为反手,导致搞了半天过不了样例。可以知道如果\(n\)这张牌在Alice手中,则Alice先手打出这张牌必胜。......
  • Codeforces Round #824 (Div. 2)
    CodeforcesRound#824(Div.2)A#include<iostream>#include<algorithm>#include<cstring>#include<cmath>#defineendl'\n'usingnamespacestd;intt,n;inlin......
  • Codeforces Round #824赛时情况&赛后总结
    前两天的CF到今天才总结,还是太鸽了呢赛时首先看了题目,由于英语障碍,我还在看A题时,YSC就已经A了(我还是太逊了)。看懂后,发现A是道水题(正常),快速切掉。随后看B,阅读倒没什么障......
  • 洛谷 CF550C Divisibility by Eight(DP/数论)
    遇事不决,小学数学。https://www.luogu.com.cn/problem/CF550C题目大意:给你一个位数不超过100的非负整数N(不含前导0)。你的任务是判断这个数字能否通过去掉其中......
  • Codeforces Global Round 22
    题目链接这场彻底打崩了,只做了A,B,C,可以看出我离退役已经不远力!A.GloryAddictstrash题不写。感觉出得很没意思。B.PrefixSumAddicts用\(s_{n-k+1}\sims_n\)......
  • CodeForces 1455G Forbidden Value
    洛谷传送门CF传送门小清新动态开点线段树优化dp题。首先题目中的if嵌套看起来就很烦,可以考虑建树,外面再套一层大的if0...end,这样就将本题转化成一个树上问题。......
  • Codeforces Round #823 (Div. 2) A-D
    比赛链接A题解知识点:贪心。对于一个轨道,要么一次性清理,要么一个一个清理。显然,如果行星个数大于直接清理的花费,那么选择直接清理,否则一个一个清理。即\(\sum\min(c,......