ZZX and Permutations
Total Submission(s): 827 Accepted Submission(s): 259
ZZX knows that a permutation can be decomposed into disjoint cycles(see https://en.wikipedia.org/wiki/Permutation#Cycle_notation). For example:
145632=(1)(35)(462)=(462)(1)(35)=(35)(1)(462)=(246)(1)(53)=(624)(1)(53)……
Note that there are many ways to rewrite it, but they are all equivalent.
A cycle with only one element is also written in the decomposition, like (1) in the example above.
Now, we remove all the parentheses in the decomposition. So the decomposition of 145632 can be 135462,462135,351462,246153,624153……
Now you are given the decomposition of a permutation after removing all the parentheses (itself is also a permutation). You should recover the original permutation. There are many ways to recover, so you should find the one with largest lexicographic order.
Then t testcases follow. In each testcase:
First line contains an integer n , the size of the permutation.
Second line contains n space-separated integers, the decomposition after removing parentheses.
n≤105 . There are 10 testcases satisfying n≤105 , 200 testcases satisfying n≤1000 .
Don't output space after the last number of a line.
2 6 1 4 5 6 3 2 2 1 2
4 6 2 5 1 3 2 1
<pre name="code" class="cpp">#include <stdio.h>
#include <string.h>
#include <set>
#include <string.h>
#define max(a,b) a>b?a:b
#define min(a,b) a>b?b:a
#define N 100005
#define lson l,m,root<<1
#define rson m+1,r,root<<1|1
using namespace std;
int n,t;
int a[N];
int sx[N];
int v[N<<2];
int w[N];
int vv[N];
int ma[N<<2];
void pushup(int root)
{
ma[root]=max(ma[root<<1],ma[root<<1|1]);
}
void build(int l,int r,int root)
{
if(l==r)
{
ma[root]=a[l];
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(root);
}
void update(int wz,int val,int l,int r,int root)
{
int m=(l+r)>>1;
if(l==r)
{
ma[root]=val;
return ;
}
if(wz<=m)
{
update(wz,val,lson);
}
else
{
update(wz,val,rson);
}
pushup(root);
}
int query(int st,int en,int l,int r,int root)
{
int m=(l+r)>>1;
int ans=-1;
if(st==l&&r==en)
{
return ma[root];
}
else
{
if(en<=m)
{
ans=query(st,en,lson);
}
else if(st>m)
{
ans=query(st,en,rson);
}
else
{
ans=max(query(st,m,lson),query(m+1,en,rson));
}
}
return ans;
}
int main()
{
scanf("%d",&t);
while(t--)
{
set<int>st;//set存的是已确定的数,就是已经被括起来的数。
memset(a,0,sizeof(a));
memset(sx,0,sizeof(sx));
memset(w,0,sizeof(w));
memset(v,0,sizeof(v));
memset(ma,-1,sizeof(ma));
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
w[a[i]]=i;//w[i]记录了i在原串的位置。
}
build(1,n,1);
for(int i=1; i<=n; i++)
{
if(sx[i]!=0)continue;//sx[i]用来存放最终的顺序,开始为0,如果不为0则已确定此位置。
int l=1;
if(!st.empty())//如果非空说明已经有括号了。
{
set<int>::iterator temp=st.lower_bound(w[i]);
//这个set<int>::iterator是容器里的指针,c++好像可以用auto,这里的作用是如果非空找出容器里不小于i的位置的第一个数。
if(temp!=st.begin())//如果temp和set中的开头元素不一样,说明w[i]前面已经有元素被括起来了,那么就从那个后一个开始。否则就从1开始。
{
temp--;
l=(*temp)+1;
}
}
int maxv=query(l,w[i],1,n,1);//找出区间l到w[i]的最大值。
if(maxv<a[w[i]+1]&&!v[a[w[i]+1]]&&w[i]!=n)
//如果这个最大值小于右边那个数并且i不在最右而且右边那个数没访问过,就选右边那个。注意此时括号只画了左半边,右边还没闭合。
{
sx[i]=a[w[i]+1];
update(w[i]+1,-1,1,n,1);//把那个更新成-1.
}
else{//此时这个括号确定了,闭合。
sx[i]=maxv;
v[maxv]=1;
for (int j=w[maxv];j<w[i];j++)//依次确定顺序。
{
sx[a[j]]=a[j+1];
}
st.insert(w[i]);//这里把i的位置存入set,也就是i被括起来了。
}
}
for(int i=1; i<n; i++)
{
printf("%d ",sx[i]);
}
printf("%d\n",sx[n]);
// printf("\n");
// printf("vvvvvv\n");
// for(int i=1; i<=n; i++)
// {
// printf("%d ",v[i]);
// }
// printf("\n\n\nasx\n");
// for(int i=1; i<=n; i++)
// printf("%d ",a[sx[i]]);
}
}
428



被折叠的 条评论
为什么被折叠?



