Codeforces Round #350 (Div. 2) E 思维模拟

给出一个合法的括号串 有LRD三种操作 LR分别是左右移动当前位置 且合法

D为删除这个括号和里面的所有 当删除完成后 位置向右移动 如果不能移动 就向左

比赛都是很久远的事情了 写这道题也是一时兴起 先写了一发暴力 先拿a记录下来与这个括号相匹配的括号位置 拿vis记录括号是否被删除 每次碰到false的括号就整体跳过

然后一气跑到了test78才停下来 想了想暴力肯定不行 就加了l数组和r数组 来记录当前位置的左右仍存在的括号在哪 每次进行移动和删除的时候都利用这个进行移动 顺便更改 有一种并查集路径压缩的感觉

然后一气跑到了test93接着超时 看了一眼数据 这时候长度已经满了 基本是()()()这样 但是我的路径压缩应该不怕这个的 比较不解

过了两天又看了一眼代码 发现我的lr数组可以做到LR是线性的 但是D的时候 我先向右寻找 如果找不到的话 再向左寻找 这个时候 由于我设定的是 如果可以找到一个true的点 就进行更改 这样可能会有很多时间被浪费在无用的D后向右探测

于是改了一下 如果D后向右没有找到可行的括号 就直接将r[w]设为n+1 直接不可行

这里和并查集不同的是 并查集的路径压缩 这条路径中的所有的fa[x]最终都会是一个顶点 而这个题目中 所有变为false的括号都不会再出现了 它必定会被我以某种方式跳过去(通过匹配括号的转移和lr数组的优化) 所以我只需要更改仍然true的点的lr就可以了

当然..做过了这道题之后去百度了一下别人的解法..看到别人题解上的链表两字 突然就明白怎么做了..

当然其实路径压缩后 实际每次LRD的操作还是O(1)的

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<queue>
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
using namespace std;
bool vis[500050];
int n,m,p;
char s[500050];
int a[500050];
char z[500050];
stack<int >sta;
int l[500050];
int r[500050];
int w;
int main()
{
    cin>>n>>m>>p;
    scanf("%s",s+1);
    scanf("%s",z+1);
    while(!sta.empty())
        sta.pop();
    for(int i=1;i<=n;i++)
    {
        if(s[i]==‘(‘)
        {
            sta.push(i);
        }
        else
        {
            a[i]=sta.top();
            sta.pop();
        }
    }
    memset(vis,true,sizeof(vis));
    for(int i=n;i>=1;i--)
    {
        if(s[i]==‘)‘)
        {
            int x=a[i];
            a[x]=i;
        }
    }
    for(int i=1;i<=n;i++)
    {
        l[i]=i-1;
        r[i]=i+1;
    }

    w= p;
    for(int i=1;i<=m;i++)
    {
        if(z[i]==‘L‘)
        {
            int ww=w;
            w=l[w];
            while(w>=1&&vis[w]==false)
            {
                if(s[w]==‘)‘)
                {
                    int x=a[w];
                    w=x;
                    w=l[w];
                }
                else
                {
                    w=l[w];
                }
            }
            l[ww]=w;
            r[w]=ww;
        }
        else if(z[i]==‘R‘)
        {
            int ww=w;
            w=r[w];
            while(w<=n&&vis[w]==false)
            {
                if(s[w]==‘(‘)
                {
                    int x= a[w];
                    w=x;
                    w=r[w];
                }
                else
                {
                    w=r[w];
                }
            }
            r[ww]=w;
            l[w]=ww;
        }
        else if(z[i]==‘D‘)
        {
            int x=a[w];
            vis[x]=false;
            vis[w]=false;
            int cs= w;
            if(s[w]==‘(‘)
            {
                int x=a[w];
                w=x;
            }
            int ww=w;
            w=r[w];
            while(w<=n&&vis[w]==false)
            {
                if(s[w]==‘(‘)
                {
                    int x= a[w];
                    w=x;
                    w=r[w];
                }
                else if(s[w]==‘)‘)
                {
                    w=r[w];
                }
            }
            if(w<=n)
            {
                r[cs]=w;
                r[ww]=w;
                l[w]=ww;
                continue;
            }
            r[cs]=n+1;
            r[ww]=n+1;
            w=cs;
            if(s[w]==‘)‘)
            {
                int x=a[w];
                w=x;
            }
            ww=w;
            w=l[w];
            while(w>=1&&vis[w]==false)
            {
                if(s[w]==‘)‘)
                {
                    int x=a[w];
                    w=x;
                    w=l[w];
                }
                else if(s[w]==‘(‘)
                {
                    w=l[w];
                }
            }
            l[ww]=w;
            l[cs]=w;
            r[w]=ww;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            for(int k=i;k<=a[i];k++)
                vis[k]=false;
            i=a[i];
        }
    }
    for(int i=1;i<=n;i++)
        if(vis[i])
            printf("%c",s[i]);
    printf("\n");
}

  

时间: 2024-09-30 11:12:30

Codeforces Round #350 (Div. 2) E 思维模拟的相关文章

【解题报告】Codeforces Round #350 (Div. 2)

题目链接 A.Holidays(Codeforces 670A) 思路 首先,若 7 能整除 n 的话,最小假期天数 m1 与最大假期天数 m2 都等于 2×n7 ."整除"提示我们可以根据 n 除以 7 的余数来分类: 余数为 0 , m1=m2=2×n7 . 余数为 1 ,考虑多出来的那天是不是周末, m1=2×n7,m2=2×n7+1 . 余数为 6 ,考虑多出来的6天中必然有周末,考虑有1天周末还是2天周末, m1=2×n7+1,m2=2×n7+2 . 其它余数,考虑多出来的那

Codeforces Round #350 (Div. 2) F. Restore a Number 模拟构造题

F. Restore a Number Vasya decided to pass a very large integer n to Kate. First, he wrote that number as a string, then he appended to the right integer k — the number of digits in n. Magically, all the numbers were shuffled in arbitrary order while

Codeforces Round #350 (Div. 2) D2 二分

五一期间和然然打的团队赛..那时候用然然的号打一场掉一场...七出四..D1是个数据规模较小的题 写了一个暴力过了 面对数据如此大的D2无可奈何 现在回来看 一下子就知道解法了 二分就可以 二分能做多少个 每次对mid求一下不够的差值 比较差值与m的大小进行l与r的变换 由于自己一向对二分比较迷茫 自己琢磨出来一套神奇的办法面对边界数据 当小于和大于的时候 抛弃mid值 当等于的时候 直接break 然后打一发while试试能否向更好的情况偏移 当然在这个题目中 如果是直接break的时候就不用

Codeforces Round #350 (Div. 2) E. Correct Bracket Sequence Editor

E. Correct Bracket Sequence Editor Recently Polycarp started to develop a text editor that works only with correct bracket sequences (abbreviated as CBS). Note that a bracket sequence is correct if it is possible to get a correct mathematical express

Codeforces Round #350 (Div. 2) 题解

Holidays Game of Robots Cinema Magic Powder - 12 Correct Bracket Sequence Editor Restore a Number Holidays #include<bits/stdc++.h> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Re

Codeforces Round #350 (Div. 2) E. Correct Bracket Sequence Editor 线段树模拟

E. Correct Bracket Sequence Editor Recently Polycarp started to develop a text editor that works only with correct bracket sequences (abbreviated as CBS). Note that a bracket sequence is correct if it is possible to get a correct mathematical express

Codeforces Round #350 (Div. 2)

A. Holidays 题意:一个礼拜有两天放假,那么n天最多和最少分别有多少天假呢? 题解:首先算最少的,就是n%7,如果余6的话则要+1.最多则是尽量让余下的天数为假期,如果余一天就加一天,余二就加两天,大于二依然只加两天,直到余六再加一天. 代码: 1 /*A*/ 2 #include<cstdio> 3 using namespace std; 4 5 int main() 6 { 7 int n; 8 while(scanf("%d",&n)!=EOF)

Codeforces Round #350 (Div. 2) E (跳转链表)

[题意]一个括号序列,你有以下三种操作:"L"光标左移:"R"光标右移:"D"删掉这个括号以及和它对应的括号之间的所有括号,并且把光标移动到被删后右边的那个括号上.如果没有了,就移动到串的末尾.现在给你原括号序列和操作,求最终结果! [分析]由于操作最多有50万个,那么简单想一下用链表来暴力模拟都是能过得去的.那么,我在这里用了类似于跳转链表来模拟这个过程!但是这里我并不是一个一个的跳转的,而是预处理了最大的括号匹配,直接跳转到可以到达的最大位置

Codeforces Round #350 (Div. 2) A

Description On the planet Mars a year lasts exactly n days (there are no leap years on Mars). But Martians have the same weeks as earthlings — 5 work days and then 2 days off. Your task is to determine the minimum possible and the maximum possible nu