Codeforces Round #423 (Div. 2) C 思维,并查集 或 线段树 D 树构造,水

Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals)

C. String Reconstruction   思维,并查集 或 线段树

题意:一个字符串被删除了,但给出 n条信息,要还原出可能的字典序最小的字符串。信息有:字符串ti,ki个位置xi,表明原本的字符串在xi位置是以字符串ti开头的。

tags:惨遭 fst,一开始把所有字符串都存下来,排序做的,结果爆内存了。。

方法1: 考虑并查集,对于字符串 ti,在位置xi,字符串长度为len,更新之后,ti~(ti+len-1)位置的祖先就都指向ti+len。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,b,a) for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 2000005;

int n, fa[N], ki, xi;
char si[N], ans[N];
int Find(int x) { return fa[x]==x ? x : fa[x]=Find(fa[x]); }
int main()
{
    scanf("%d", &n);
    rep(i,1,N-1) fa[i]=i, ans[i]=‘a‘;
    int mx=0;
    rep(cn,1,n)
    {
        scanf("%s %d", si+1, &ki);
        int len=strlen(si+1);
        rep(ck,1,ki)
        {
            scanf("%d", &xi);
            mx=max(mx, xi+len-1);
            int y=xi;
            while((y=Find(y)) <= xi+len-1)
            {
                ans[y]=si[y-xi+1];
                fa[y]=y+1;
            }
        }
    }
    rep(i,1,mx) putchar(ans[i]);

    return 0;
}

方法2: 直接树状数组或线段树更新

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2001000;
char ans[maxn];
char c[maxn];
long long   t[maxn];

void add(int k)
{
    while(k < maxn)
    {
        t[k]++;
        k += k & -k;
    }
}
int sum(int x)
{
    long long  sum = 0;
    while(x)
    {
        sum += t[x];
        x -= x & -x;
    }
    return sum;
}
void updata(int l, int r, int k)
{
    if(l == r)
    {
        if(!ans[l])
        {
            add(l);
            ans[l] = c[k];
        }
        return ;
    }
    int mid = (l + r) >> 1;
    if(sum(mid)-sum(l-1) != mid - l + 1)
        updata(l, mid, k);
    if(sum(r)-sum(mid) != r - mid)
        updata(mid + 1, r, k + mid - l + 1);
}
int main()
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        int lans = 0;
        memset(ans,0,sizeof(ans));
        memset(t,0,sizeof(t));
        while(n--)
        {
            int m = 0;
            scanf("%s%d", c, &m);
            int len = strlen(c);
            for(int i = 0; i < m; i++)
            {
                int l;
                scanf("%d", &l);
                lans = max(lans, l + len);
                updata(l, l + len-1, 0);
            }
        }
        for(int i = 1; i < lans; i++)
        {
            putchar(ans[i]? ans[i]: ‘a‘);
        }
        printf("\n");
    }
    return 0;
}

D. High Load    树构造,水,dfs

题意:n个点的树,已知有k个叶子节点,要使得树上的最长链最短,构造出这树。

tags:大水题,比赛的时候竟然没去看。。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,b,a) for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 200005;

ll n, k;
vector<ll > G[N];
void dfs(int u, int fa)
{
    for(auto to : G[u]) if(to!=fa)
    {
        printf("%d %d\n", u, to);
        dfs(to, u);
    }
}
int main()
{
    scanf("%lld %lld", &n, &k);
    ll cnt=1, j;
    while(cnt<n)
    {
        for(j=1; j<=k, cnt+j<=n; ++j)
        {
            ll u=max(1LL, cnt+j-k);
            G[u].PB(cnt+j); G[cnt+j].PB(u);
        }
        cnt=cnt+j;
    }
    ll ans=(n-1+k-1)/k*2;
    if(n-1-k*(ans/2-1)==1) --ans;
    printf("%lld\n", ans);
    dfs(1, 0);

    return 0;
}

时间: 2024-12-26 00:13:51

Codeforces Round #423 (Div. 2) C 思维,并查集 或 线段树 D 树构造,水的相关文章

Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) E. DNA Evolution 树状数组

E. DNA Evolution time limit per test 2 seconds memory limit per test 512 megabytes input standard input output standard output Everyone knows that DNA strands consist of nucleotides. There are four types of nucleotides: "A", "T", "

Codeforces Round #623 (Div. 2) D.Recommendations 并查集

ABC实在是没什么好说的,但是D题真的太妙了,详细的说一下吧 首先思路是对于a相等的分类,假设有n个,则肯定要把n-1个都增加,因为a都是相等的,所以肯定是增加t小的分类,也就是说每次都能处理一个分类,复杂度是O(n^2),这个思路很好写,优先队列随便搞一下就行了,但是题目中N = 2 * 1e5,n^2肯定是不行的,然后就是这个很巧妙的方法了,cf官方的题解我没看懂...有点尴尬,它也没给标程,但是cf的题解好像不是这个方法 看了网上用并查集的方法,首先以t为关键字从大到小排序,然后用并查集维

Codeforces Round #423 (Div. 2) D. High Load(构造题)

题目链接:Codeforces Round #423 (Div. 2) D. High Load 题意: 给你一个数n和k,让你构造出一颗树,有k个叶子节点,使得这棵树的任意两个点的距离的最大值最小. 题解: 显然要使得这棵树的任意两个点的距离的最大值最小,每个点离树根越近越好. 然后要求有k个叶子节点,所以我就任意选一个点为根,然后构成一棵m叉的树就行了. 最大距离的最小值就是离根最远的和最近的加一加就行了. 1 #include<cstdio> 2 #define F(i,a,b) for

Codeforces Round #459 (Div. 2) C 思维,贪心 D 记忆化dp

Codeforces Round #459 (Div. 2) C. The Monster 题意:定义正确的括号串,是能够全部匹配的左右括号串. 给出一个字符串,有 (.). ? 三种字符, ? 可以当作 ( 可 ) . 问这个字符串有多少个子串是正确的括号串. tags:好考思维,想不到.. 预处理出每个字符向左向右最多可以匹配到哪里,再 O(n*n) 枚举所有区间,看是否符合条件. // C #include<bits/stdc++.h> using namespace std; #pra

Educational Codeforces Round 14 D. Swaps in Permutation (并查集orDFS)

题目链接:http://codeforces.com/problemset/problem/691/D 给你n个数,各不相同,范围是1到n.然后是m行数a和b,表示下标为a的数和下标为b的数可以交换无数次.问你最后字典序最大的数列是什么. 将下面的a和b用并查集联系起来存到祖节点对应的数组中,然后从大到小排序数组,最后依次按照父节点的数组中的顺序输出. 也可以用dfs的方法解(略麻烦),形成一个环路的就在一个数组中... 1 //并查集 2 #include <bits/stdc++.h> 3

Codeforces Round #423 Div. 2 C-String Reconstruction(思维)

题目大意:告诉你n个字符串以及这些字符串在字符串s中出现的位置(x1,x2.....xn),要求在满足上述条件的情况下,求出字典序最小的字符串s. 解题思路:主要问题是,如果直接模拟是会超时的,比如vvvvvvvvvv 3 1 2 3这样就有大量重复(因为题目说了这些字符串位置不会相互矛盾,所以已经有了字符的地方可以不用管了),每次都重复了len-1的长度,如果这段字符串长度为1e6那很容易就超时了.所以这里添加一个pre记录上一次字符串的末尾位置(因为题目说了给出的位置时递增的),每次比较一下

Codeforces Round #143 (Div. 2) (ABCD 思维场)

题目连链接:http://codeforces.com/contest/231 A. Team time limit per test:2 seconds memory limit per test:256 megabytes One day three best friends Petya, Vasya and Tonya decided to form a team and take part in programming contests. Participants are usually

Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) Problem A - B

Pronlem A In a small restaurant there are a tables for one person and b tables for two persons. It it known that n groups of people come today, each consisting of one or two people. If a group consist of one person, it is seated at a vacant one-seate

Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals)D. High Load

题意:出n个点,其中k个叶子节点,问构造出的树最远的两个点最近是多少 思路:以一个点为中心,然后m个伸出,一层层扩散,(n-1)%m==k,如果k==0,即可以平分,长度就是2*(n-1)/m,如果取模为k==1,说明多出一个,+1,其他的话,就是最后一层补k个,但是最长的还是+2 1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int main(){ 5 int n,m; 6 cin>>n>>m; 7 int