Codeforces 828C String Reconstruction【并查集巧妙运用】

LINK


题目大意

给你n个串和在原串中的出现位置,问原串


思路

直接跑肯定是GG
考虑怎么优化
因为保证有解,所以考虑过的点我们就不再考虑
用并查集维护当前每个点之后最早的没有被更新过的点
然后就做完了,很巧妙对吧


c++//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
  bool w = 1;x = 0;
  char c = getchar();
  while (!isdigit(c) && c != '-') c = getchar();
  if (c == '-') w = 0, c = getchar();
  while (isdigit(c)) {
    x = (x<<1) + (x<<3) + c -'0';
    c = getchar();
  }
  if (!w) x = -x;
}
template <typename T>
void Write(T x) {
  if (x < 0) {
    putchar('-');
    x = -x;
  }
  if (x > 9) Write(x / 10);
  putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 1e6 + 10;
int n, fa[N << 1];
char s[N << 1], c[N];
void init() {
  fu(i, 1, (N << 1) - 1) fa[i] = i;
}
int find(int x) {
  return x == fa[x] ? x : fa[x] = find(fa[x]);
}
int main() {
  Read(n);
  init();
  int maxl = 0;
  fu(i, 1, n) {
    scanf("%s", c + 1);
    int num, len = strlen(c + 1), pos;
    Read(num);
    fu(j, 1, num) {
      Read(pos);
      maxl = max(maxl, pos + len - 1);
      for (int k = find(pos); k <= pos + len - 1; k = find(k)){
        s[k] = c[k - pos + 1];
        fa[k] = k + 1;
      }
    }
  }
  fu(i, 1, maxl) if (!s[i]) s[i] = 'a';
  printf("%s", s + 1);
  return 0;
}

原文地址:https://www.cnblogs.com/dream-maker-yk/p/9818587.html

时间: 2024-10-30 07:07:35

Codeforces 828C String Reconstruction【并查集巧妙运用】的相关文章

CodeForces 828C String Reconstruction(并查集思想)

题意:给你n个串,给你每个串在总串中开始的每个位置,问你最小字典序总串. 思路:显然这道题有很多重复填涂的地方,那么这里的时间花费就会特别高. 我们维护一个并查集fa,用fa[i]记录从第i位置开始第一个没填涂的位置,那每次都能跳过涂过的地方.每次填完当前格就去填find(fa[i + 1]). ps:一定要合并,不然超时. 代码: #include<stack> #include<vector> #include<queue> #include<set>

codeforces 468B two set(并查集)

codeforces 468B two set(并查集)n+1 表示 B 组 n+2 表示 A 组 按照 这题的做法 应该是 如果 满足 num[ i ] a-num[ i ] 则他们同一组 但不一定 就一定是 都是 A 组 也可能都是 B 组 然而如果不满足这个条件的话,就直接加入 B组 然后如果满足 num[ i ] b-num[ i ] 则加入同一组 然后不满足就 加入 A 组 1 #include <bits/stdc++.h> 2 using namespace std ; 3 4

Codeforces 278C Learning Languages(并查集) 求连通块

Codeforces 278C Learning Languages(并查集) 求连通块 为什么最后还要getfather 一遍 比如 x 是 y 的父亲 然后你 Union(x,z) 然后 z 变成了 x 父亲 然后 y 的祖先就是错的了 题解 求一个无向图中有几个连通块 sum 特判 一下 如果 每一个人的语言都为 0 则答案为 sum 其他 答案则为 sum - 1 1 #include <bits/stdc++.h> 2 using namespace std ; 3 4 const

Codeforces 292D Connected Components (并查集)

Codeforces 292D Connected Components (并查集) 题意 给出一张无向图,每次询问删去第Li--Ri 条边 求此时有多少个连通块 题解 求出一个前缀 Li 表示 加入前 i 条边时图的连通状况 以及一个后缀 Ri 表示 加入后 i 条边时图的连通状况 对于每个询问 删除 s--t 条边 只要将 L s-1 和 R t+1 合并 一下 就行了 合并 其实 就是讲 s-1 和 t+1 对应的 f[ i ] Union 一下就行了 为什么 这就相当于把前缀 i 和 后

Codeforces 650C Table Compression (并查集)

题意:M×N的矩阵 让你保持每行每列的大小对应关系不变,将矩阵重写,重写后的最大值最小. 思路:离散化思想+并查集,详见代码 好题! 1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4 #include <algorithm> 5 #include <cmath> 6 #include <cstdlib> 7 #include <bits/stdc

Codeforces Gym 100463E Spies 并查集

Spies Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100463/attachments Description In the aftermath of Canada’s annexation of Pittsburgh tensions have been pretty high between Canada and the US. You have personally been hired

CodeForces 731C C - Socks 并查集

Description Arseniy is already grown-up and independent. His mother decided to leave him alone for m days and left on a vacation. She have prepared a lot of food, left some money and washed all Arseniy's clothes. Ten minutes before her leave she real

CodeForces 722C Destroying Array (并查集)

题意:给定 n 个数,然后每次破坏一个位置的数,那么剩下的连通块的和最大是多少. 析:用并查集来做,从后往前推,一开始什么也没有,如果破坏一个,那么我们就加上一个,然后判断它左右两侧是不是存在,如果存在,那么就合并起来, 然后不断最大值,因为这个最大值肯定是不递减,所以我们一直更新就好. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <s

CodeForces 566D Restructuring Company (并查集+链表)

题意:给定 3 种操作, 第一种 1 u v 把 u 和 v 合并 第二种 2 l r 把 l - r 这一段区间合并 第三种 3 u v 判断 u 和 v 是不是在同一集合中. 析:很容易知道是用并查集来做,但是如果单纯的用并查集,肯定是要超时的,所以要用链表,如果合并了,就把链表指向, 这样就搞定了这个题. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #i