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

Codeforces Round #816 (Div. 2)

时间:2022-08-21 13:12:15浏览次数:80  
标签:le Point int rep Codeforces dijkstra Div include 816

题面

A. Crossmarket

不妨设 \(n\ge m\),则答案为 \(n+2(m-1)\)。
特别地,\(n=1,m=1\) 时答案为 \(0\),注意特判。

View Code
#include<stdio.h>
#include<algorithm>
 
int T,n,m;
 
int main() {
    scanf("%d",&T);
    while (T--) {
        scanf("%d%d",&n,&m);
        if (n<m) std::swap(n,m);
        if (n==1) puts("0");
        else printf("%d\n",n+(m-1<<1));
    }
    return 0;
}

B. Beautiful Array

为了方便,不妨令 \(0\le a_1,a_2,\cdots,a_{n-1}<k,0\le a_n-kb<k\)。
这样就能保证 beauty 值为 \(b\) 了。

然后问题转化为:
构造 \(n\) 个小于 \(k\) 的非负整数,使它们的和为 \(s-kb\)。

显然 \(0\le s-kb\le n(k-1)\) 时有解,随便做一下就行。

View Code
#include<stdio.h>
#define int long long
 
int T,n,k,b,s,x;
 
signed main() {
    scanf("%lld",&T);
    while (T--) {
        scanf("%lld%lld%lld%lld",&n,&k,&b,&s);
        if ((s-=k*b)<0) { puts("-1"); continue; }
        if ((k-1)*n<s) { puts("-1"); continue; }
        for (int i=1; i<n; ++i)
            x=(s>=k-1?k-1:s),
            printf("%lld ",x),s-=x;
        printf("%lld\n",k*b+s);
    }
    return 0;
}

C. Monoblock

作为一个 C 题来说,感觉出得挺不错的。

考虑 \(a_i\) 对答案的贡献。容易写出式子:

\[[a_i\ne a_{i-1}](i-1)(n-i+1) + [a_i\ne a_{i+1}]i(n-i) \]

单点修改显然很好维护。

现在的问题是怎么处理答案的初始值。

其实将读入的序列 \(a\) 当成 \(n\) 次单点修改就好了。

那么我们可以认为最初 \(a_i\) 均为 \(0\),此时的答案即为 \(\dfrac{n(n+1)}2\)。

View Code
#include<stdio.h>
typedef long long ll;
 
const int N=1e5+5;
 
int n,m,i,x,a[N]; ll ans;
 
void upd(int i,int x) {
    ll d1=(x!=a[i-1])-(a[i]!=a[i-1]);
    ll d2=(x!=a[i+1])-(a[i]!=a[i+1]);
    ans+=d1*(i-1)*(n-i+1)+d2*i*(n-i);
    a[i]=x;
}
 
int main() {
    scanf("%d%d",&n,&m);
    ans=1ll*n*(n+1)>>1;
    for (int i=1; i<=n; ++i)
        scanf("%d",&x),upd(i,x);
    while (m--)
        scanf("%d%d",&i,&x),upd(i,x),
        printf("%lld\n",ans);
    return 0;
}

D. 2+ doors

位运算题,优先考虑能否按位处理。然后发现确实可以。

按位拆分之后目标不变,仍然要让字典序最小。

约束条件分为两类:

  1. 某两个位置均为 0。
  2. 某两个位置至少有一个 1。

采取贪心策略,从前往后填数,在满足约束条件的前提下尽量填 0。
对于第 1 类约束条件,预先填 0 即可。
对于第 2 类约束条件,可以建个图,然后乱维护一波。

实现方法比较正常的话,时间复杂度应该是 \(O((n+m)\log V)\),其中 \(V\) 为值域。

View Code
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#define rep(i,l,r) for (int i=l; i<=r; ++i)
#define repE(i,x) for (int i=lst[x]; i; i=E[i].pre)

const int N=1e5+5,M=2e5+5;

int n,m,x,y,w,cnt;
int lst[N],ans[N],v[N];
struct Node { int x,y,w; }Q[M];
struct Edge { int y,pre; }E[M<<1];

inline int read() {
    int x=0; char ch=getchar();
    while (!isdigit(ch)) ch=getchar();
    while (isdigit(ch)) x=x*10+(ch^48),ch=getchar();
    return x;
}

int main() {
    n=read(),m=read();
    rep(i,1,m) {
        x=read(),y=read(),w=read();
        Q[i]={x,y,w};
    }
    rep(k,0,29) {
        cnt=0;
        memset(lst,0,sizeof lst);
        memset(v,-1,sizeof v);
        rep(i,1,m) {
            x=Q[i].x,y=Q[i].y,w=(Q[i].w>>k)&1;
            if (w&&x!=y)
                E[++cnt]={y,lst[x]},lst[x]=cnt,
                E[++cnt]={x,lst[y]},lst[y]=cnt;
            else v[x]=v[y]=w;
        }
        rep(i,1,n) if (!v[i]) //已经填0
            repE(j,i) v[E[j].y]=1; //相邻点必须填1
        rep(i,1,n) {
            if (v[i]==1) {
                ans[i]|=(1<<k);
                continue;
            }
            v[i]=0;
            repE(j,i) v[E[j].y]=1;
        }
    }
    rep(i,1,n) printf("%d ",ans[i]);
    return 0;
}

E. Long Way Home

从最简单的情形入手。
\(k=0\) 时就是单源最短路模板,用 dijkstra 做即可。
\(k=1\) 好像就不太会做了。

先跑一遍 dijkstra,设从 \(1\) 到 \(i\) 的最短路长度为 \(d_i\)。

现在允许飞一次,那么新的最短路长度 \(d'_i\) 满足

\[d'_i=\min\limits_{1\le j\le n}\{d_j+(i-j)^2\} \]

我超,斜率优化。
平时没怎么写过,但可以手搓一下。
时间复杂度为 \(O(n)\)。

注意飞完之后还是可以继续走图上的边的。所以最后再跑一遍 dijkstra。

\(k>1\) 的情况也同理,做 \(k\) 轮 dijkstra 和斜优 dp,最后再加一轮 dijkstra 即可。

dijkstra 堆优化使用 priority_queue,则总时间复杂度为 \(O(km\log m)\)。

View Code
#include<stdio.h>
#include<queue>
#define rep(i,l,r) for (int i=l; i<=r; ++i)
typedef long long ll;

const int N=1e5+5;

int n,m,k,x,y,w,cnt,lst[N]; ll d[N];

struct Edge { int y,w,pre; }E[N<<1];

struct Node { int x; ll dis; };
bool operator < (Node p,Node q) { return p.dis>q.dis; }
std::priority_queue<Node>Q;

struct Point { int x; ll y; }L[N];
bool cmp(Point a,Point b,Point c,Point d) { 
    return (a.y-b.y)*(c.x-d.x)>(c.y-d.y)*(a.x-b.x); //k(AB)>k(CD)
}

void dijkstra() {
    rep(i,1,n) Q.push({i,d[i]});
    while (!Q.empty()) {
        Node q=Q.top(); Q.pop();
        if (q.dis!=d[q.x]) continue;
        for (int i=lst[q.x],y; i; i=E[i].pre)
            if (d[y=E[i].y]>d[q.x]+E[i].w) {
                d[y]=d[q.x]+E[i].w;
                Q.push({y,d[y]});
            }
    }
}

void dp() {
    int l=1,r=0;
    rep(i,1,n) { //单调队列维护下凸壳
        Point t={i<<1,d[i]+1ll*i*i};
        while (l<r&&cmp(L[r-1],L[r],L[r],t)) --r;
        L[++r]=t;
    }
    rep(i,1,n) {
        Point t1={0,0},t2={1,i};
        while (l<r&&cmp(t1,t2,L[l],L[l+1])) ++l;
        d[i]=L[l].y-1ll*L[l].x*i+1ll*i*i;
    }
}

int main() {
    scanf("%d%d%d",&n,&m,&k);
    rep(i,1,m)
        scanf("%d%d%d",&x,&y,&w),
        E[++cnt]={y,w,lst[x]},lst[x]=cnt,
        E[++cnt]={x,w,lst[y]},lst[y]=cnt;
    rep(i,2,n) d[i]=1e11;
    while (k--) dijkstra(),dp();
    dijkstra();
    rep(i,1,n) printf("%lld ",d[i]);
    return 0;
}

F. Crop Squares

牛逼题,可惜赛时没啥时间想了。

待会再补。

Result: Rank 36 (ABCDE), \(\bf{{\color{purple}{2039}}\to{\color{orange}{2157}}}\),小号2 bcr_233

标签:le,Point,int,rep,Codeforces,dijkstra,Div,include,816
From: https://www.cnblogs.com/REKonib/p/16609814.html

相关文章

  • [Codeforces Round #816 (Div. 2)] D. 2+ doors
    这次Div.2比之前我打的有些要难啊,前三道题就耗了好多时间,D题干脆摆烂了。。。还是太逊了对于一个\(x\),有\(x|y_i=z_i\),那么我们设\(num[x]=z_1\)&\(z_2\)&\(z_3\)..........
  • 【长期】板刷Codeforces 1500-1700 的构造题
    【长期】板刷Codeforces1500-1700的构造题https://codeforces.com/problemset/page/1?tags=constructive+algorithms%2C1500-1700&order=BY_RATING_ASC每天三道,记录一......
  • Codeforces 1720 D, E
    D1设\(dp(i)\)表示考虑前i个数的最长子序列。枚举\(j\),从\(dp(j)+1\)转移到\(dp(i)\),转移条件就是题中给的那个不等式。发现\(i-j\)不能超过\(300\),暴力枚举即可。时间......
  • 消除div独占一行
    https://zhidao.baidu.com/question/2053672297762439507.htmldiv默认是display:block的。block就是块状的意思,也就是相当于div前后各加一个换行的效果,于是这个div就独......
  • [题解] Codeforces 1720 E Misha and Paintings 结论
    算是诈骗题?令一开始就存在的颜色数为cnt。k>=cnt的情况,显然每次找一个出现不止一次的颜色,然后把这个颜色的恰好一个方块替换成一种没有出现过的颜色就可以了,\(k-cnt\)次解......
  • 如何将一个div水平垂直居中?6种方法做推荐
    https://www.cnblogs.com/Julia-Yuan/p/6648816.html方案一:div绝对定位水平垂直居中【margin:auto实现绝对定位元素的居中】,兼容性:,IE7及之前版本不支持di......
  • codeforces963D. Frequency of String【哈希】
    我的腿让我停下,可是我的心却不许我这么做今天又是为了明知多半不可能的事情奔波一早,一天里,出了很多丑,犯了很多错,见了很多人,有了很多意想不到的收获,我选择了我的生存方式......
  • Codeforces Round #815 (Div. 2) 题解
    CF1720A.BurenkaPlayswithFractions给出两个分数$\dfrac{a}{b}$和\(\dfrac{c}{d}\),你每次操作能够选择其中一个分数的分子或分母,将其乘上任意一个整数(当然不能......
  • Codeforces 杂题集
    本文主要把近期\(CF-Div.2\)的\(A,B,C,D\)题进行做Round815A题意给你两个分数\(\frac{a}{b},\frac{c}{d}\),问你最少几次使两个分数相等。Solution首先考虑,最......
  • Codeforces Round #815 (Div. 2) D2 Xor-Subsequence (hard version)
    原题链接\(A>B\),总是有二进制下从高到低的前\(k\)位相等,第\(k+1\)位\(A\)是\(1\),\(B\)是\(0\)本题中\(A=a_i\oplusj\),\(B=a_j\oplusi\),这里有一个很奇妙的性质(手玩或者......