JZOJ4708. 【NOIP2016提高A组模拟8.20】奇洛金卡达 倒着做的思想+并查集维护

来源:互联网 发布:淘宝昵称怎么修改 编辑:程序博客网 时间:2024/04/30 12:05

题目大意

给定一个长度小于等于k的字符串和q,表示现在有q个操作,每个操作给定两个参数li,ri表示把现在的字符串第liri把其中编号为奇数的按顺序写下来,再在后面把编号为偶数的按顺序写下来,最后把写出的新字符串加在区间后面。
一下为两个例子:
1s1s2s3s4s5s6s7li=3ri=5s1s2s3s4s5s3s5s4s6s7
2s1s2s3s4s5s6s7li=4ri=7s1s2s3s4s5s6s7s5s7s4s6
给定每组li,ri要求输出操作完的字符串的前k位是什么。

q5000
k3000000
li,ri109

解题思路

首先一个显然的性质,对于当前的字符串,在第k个·字符后面的肯定是没有用的。考虑题目给定的操作,由于字符串是动态变换的,所以很难维护字符串的信息。那么我们考虑对于操作,从后往前做,那么就能保证每确定一个位置,这个位置上的字符就不会变。

照着这个思路我们只需每次找出字符串的第li个位置和第li+ri个位置,分别表示当前需要复制区间的其实位置以及复制后区间的起始位置。我们只需把后面的区间上的位置打上与前面某个位置相等的标记。然后由于这个区间已经确定下来,所以把这段区间标记为“删除”,并且在我们下次找区间第li个位置时就不能算上“删除”的位置。

现在就又遇到了两个问题,以一个是怎么找到第li个未被打上“删除”的位置,以及上某个位置下一个未被打上“删除”的位置。我们观察一下数据范围,我们发现只有5000个修改操作,并且一个操作肯定是连续的一段区间(就算不连续,中间的位置也一定是被打上删除标记的)。那么我们可以用并查集把相邻的“删除”位置并到一起,并记录下它覆盖的区间。那么找位置时可用的就是两个被“删除”的区间有有多少个位置,只需O(n)扫一遍就可以知道位置。对于第二个问题也一样,由于我们把相邻的“删除”的区间并在了一起,所以加入下一个位置是被“删除”了的,就只需跳到这个区间右边界+1就可以了。

最后输出时扫一遍就可以了。

程序

//YxuanwKeith#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int MAXN = 1e5 + 5, MAXM = 5e3 + 5, MAXK = 3e6 + 5;struct Node {    int l, r;    Node(int a, int b) {l = a, r = b;}    Node() {}};bool flag[MAXK];Node D[MAXM], Coor[MAXK];char S[MAXK], T[MAXK];int n, k, len, top, l[MAXM], r[MAXM], ord[MAXK], lst[MAXK], deep[MAXK];int Get(int s) {    int get = 0;    for (int j = 2; j <= top; j ++) {        if (get + D[j].l - 1 - D[j - 1].r >= s) {            return D[j - 1].r + s - get;            break;        } else get += D[j].l - 1 - D[j - 1].r;    }    return 0;}int Find(int x) {    if (ord[x] == x) return x;    ord[x] = Find(ord[x]);    return ord[x];}void Merge(int x, int y) {    int fx = Find(x), fy = Find(y);    if (fx == fy) return;    if (deep[fx] > deep[fy]) swap(fx, fy);    ord[fx] = fy;    Coor[fy] = Node(min(Coor[fx].l, Coor[fy].l), max(Coor[fx].r, Coor[fy].r));    if (deep[fx] == deep[fy]) deep[fy] ++;}void Maketag(int p) {    flag[p] = 1;    if (flag[p - 1]) Merge(p, p - 1);    if (flag[p + 1]) Merge(p, p + 1);}int Next(int s) {    int p = s + 1;    while (p <= k && flag[p]) p = Coor[Find(p)].r + 1;    if (p > k || flag[p]) return 0;    return p;}int main() {    scanf("%s", S + 1);    len = strlen(S + 1);    scanf("%d%d", &k, &n);    for (int i = 1; i <= n; i ++)         scanf("%d%d", &l[i], &r[i]);    D[1] = Node(0, 0), D[2] = Node(k + 1, k + 1);    top = 2;    for (int i = 1; i <= k; i ++) ord[i] = lst[i] = i, Coor[i] = Node(i, i);    for (int i = n; i; i --) {        int s1 = Get(l[i]), s2 = Get(r[i] + 1), len = r[i] - l[i] + 1;        if (s2 == 0) continue;        int cnt = 1, p = ((l[i] & 1) || len == 1) ? s1 : Next(s1), t = s2, Last = 0;        for (; ; cnt ++) {            Maketag(t);            lst[t] = p;            Last = max(Last, t);            if (cnt == len) break;            int tmp = Next(t);            if (!tmp) break;            t = tmp;            if (cnt == (len + (l[i] & 1)) / 2) p = (l[i] & 1) ? Next(s1) : s1; else                 p = Next(Next(p));        }        int del = 0;        for (int i = 1; i <= top; i ++) {            p = i - del;            D[p] = D[i];            if (Find(D[p].r) == Find(s2)) del ++;        }        top -= del;        D[++ top] = Coor[Find(s2)], p = top;        for (; p > 1 && D[p].l < D[p - 1].l; p --)             swap(D[p], D[p - 1]);    }    int get = 0;    for (int i = 1; i <= k; i ++) {        if (lst[i] == i) {            get ++;            T[i] = S[get];        } else T[i] = T[lst[i]];        printf("%c", T[i]);    }    printf("\n");}
3 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 代扣代缴个税申报逾期申报怎么办 个税申报错了怎么办 个税公司报错了怎么办 个税为0没申报怎么办 建筑老项目无法取得发票怎么办 客户说选的地砖不好看怎么办 外国客户打电话来不敢接怎么办 电话营销遇到不礼貌的客户怎么办 去领导家被拒绝怎么办 共享电车没电了怎么办 享骑电单车没电怎么办 小车前轮刹车卡钳卡死了怎么办 耐克气垫鞋扎了怎么办 骑自行车右大腿根痛怎么办 骑车骑得膝盖疼怎么办 骑了自行车腿疼怎么办 群面没有被问题怎么办 群面没有被提问怎么办 校招解约学校不盖章怎么办 科目三老是跑偏怎么办 面试官说你不好怎么办 面试紧张心态调整不过来怎么办 面试官问缺乏经验怎么办 办好入职手续后就想辞职怎么办 新店长入职应该怎么办 刚入职怀孕了辞职店长不同意怎么办 派遣证丢了怎么办补办 出国留学回来怎么办派遣证 报到证坏了一边怎么办 江苏报到证丢了怎么办 河南报到证丢了怎么办 报到证丢失10年怎么办 退休时无派遣证怎么办 档案里没有派遣证怎么办 档案中派遣证丢失怎么办 中专毕业后想读大学该怎么办 软考准考证丢了怎么办 面试薪资要低了怎么办 应聘等通知没有电话回复怎么办 学生信息表里的籍贯不对怎么办? 小学生信息表里的籍贯不对怎么办?