A - Streets of Working Lanterns - 2

警察阿纳托利再次监视一个无组织犯罪集团散布被禁止的亚洲绘画的巢穴。目前,犯罪分子还共享无线互联网,任何人都可以匿名使用。巢穴仍然只有一个入口,也是一个出口。当有人进入巢穴时,阿纳托利在他的记事本上写一个开口圆括号,当有人出来时,他写一个闭合圆括号。
阿纳托利决定不吃甜甜圈,以免像前一次那样破坏记录,但尽管如此,当他从记事本上撕下一张纸来提交刑事案件时,却不小心把它撕成了碎片。他不想让老板对他大喊大叫,所以他必须按照正确的顺序连接部件来恢复记录。记事本的布局可以确定这些碎片的顶部和底部,这对他来说很好。阿纳托利在开始监视之前和结束监视之后都确保罪犯的巢穴是空的。

输入
输入第一行包含单个整数 n(1 ≤  n ≤  2e5)——写有开括号和闭括号的纸张的张数。
接下来的 n 行只包含字符 “(” 和 “)” ——这些是写在片段上的字符串。括号的总数不超过2e5个。

输出
如果给定的部分可以连接,这样得到的字符串就不会与语句相矛盾,则在第一行 ”YES“ 中输出,不带引号。在第二行中,输出n个由空格分隔的整数——它们必须连接的顺序中的个数。这些片段按照输入中提到的顺序从一开始编号。
如果Anatoliy搞砸了什么,并且给定的片段不能形成正确的记录,则在没有引号的唯一一行 ”NO“ 中输出。

Input1
3
(
()
)
Output1
YES
1 2 3

Intput2
3
)))
((
(
Output2
YES
2 3 1

Input3
3
)))
((
)
Output3
NO

解析:在代码中

#include 
using namespace std;
#define int long long
#define endl '\n'
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int gcd(int a,int b) { return b? gcd(b,a%b) : a; }
typedef pair PII;
const double PI=acos(-1.0);
const int N=2e6+10;
int n;
stack  q;
struct node
{
    int l,r,id;
}a[N],b[N],c[N],d[N];   //分四组
bool cmp1(node x,node y)        //按照右括号从小到大排序 此时l>=r,剩下的左括号有利于后续右括号的抵消
{
    if (x.r!=y.r) return x.ry.l;
}
bool cmp2(node x,node y)        //按照左括号从大到小排序 (对不起,我也很迷~~)
{
    if (x.l!=y.l) return x.l>y.l;
    else return x.r>y.r;
}
string p;
void solve()
{
    cin>>n;
    int l1=0,l2=0,l3=0,l4=0;
    for (int k=0;k>p;
        for (int i=0;i=r) b[l2].l=l,b[l2].r=r,b[l2++].id=k+1;
            else d[l4].l=l,d[l4].r=r,d[l4++].id=k+1;
        }
        else if (l==0&&r!=0) c[l3].l=0,c[l3].r=r,c[l3++].id=k+1;
    }
    sort (b,b+l2,cmp1);
    sort (d,d+l4,cmp2);
    bool falg=1;                            //之后暴力判断
    int cnt=0;      
    for (int i=0;i>T;
    while (T--) solve(); 
    return 0;
}

你可能感兴趣的:(算法,数据结构)