2018SD省队集训R1 D7

T1

题解:

代码:

T2

2018SD省队集训R1 D7_第1张图片

题解:

很明显我们可以转化一下看看,贪心的从最小的开始选择,每一个数字可以连向左边还没被扩进去的最大值,右边的第一个,或者是自己,维护区间最大值可以用线段树,维护哪些区间被用过可以用set。

2018SD省队集训R1 D7_第2张图片
则234被扎死口,234的值都是0;56未被扎死口,6的值是0。可以发现,被扎死口的元素值为0,值为0的元素不一定被扎死口,因为还可以向左连5,这里扎死口的概念就是能否越过这个点向左找值的意思

代码:

#include 
#include 
#include 
#define INF 1e9
using namespace std;
const int N=100005;
set<int>s;int maxx[N*4],a[N],pos[N],n,ans[N];
void updata(int now){maxx[now]=max(maxx[now<<1],maxx[now<<1|1]);}
void change(int now,int l,int r,int x,int v)
{
    if (l==r){maxx[now]=v;return;}
    int mid=(l+r)>>1;
    if (x<=mid) change(now<<1,l,mid,x,v);
    else change(now<<1|1,mid+1,r,x,v);
    updata(now); 
}
int qurry(int now,int l,int r,int lrange,int rrange)
{
    if (lrange>rrange) return 0;
    if (lrange<=l && rrange>=r) return maxx[now];
    int mid=(l+r)>>1,ans=0;
    if (lrange<=mid) ans=qurry(now<<1,l,mid,lrange,rrange);
    if (rrange>mid) ans=max(ans,qurry(now<<1|1,mid+1,r,lrange,rrange));
    return ans;
}
void bl(int l,int r)
{
    for (int i=l;i<=r;i++) 
      change(1,1,n,i,0),s.insert(i);
    int z=r-l+1;
    for (int i=0;i<=r-l;i++) ans[a[l+(i-1+z)%z]]=a[l+i];
}
int main()
{
    freopen("perm.in","r",stdin);
    freopen("perm.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<=n;i++) pos[a[i]]=i;
    for (int i=1;i<=n;i++) change(1,1,n,pos[i],i);
    s.insert(0);
    for (int i=1;i<=n;i++)
      if (!ans[i])
      {
        int wz=0,now=pos[i],maxx=0,zuo;
        wz=*--s.lower_bound(now);
        if (qurry(1,1,n,now,now)!=0) maxx=i,zuo=now;
        //可能已经被选了(被向右扩的结果 ,不能用s.count的原因是这个点不一定被扎死口,可能后边的还向前连 
        //被扎死口的一定是0,0的不一定被扎死口 
        if (!s.count(now+1)) //右边的已经被选过了
        {
            if (maxx1]) maxx=a[now+1],zuo=now+1;
        } 
        if (wz+1<=now-1)
        {
            int z=qurry(1,1,n,wz+1,now-1);
            if (maxxif (zuo==now)
        {
            s.insert(now);change(1,1,n,now,0);
            ans[i]=i;
            continue;
        }
        if (zuo==now+1)
        {
            change(1,1,n,now+1,0);
            continue;
        }
        bl(zuo,now);
      }
    for (int i=1;i<=n;i++) printf("%d ",ans[i]);
}

T3

题解:

代码:

你可能感兴趣的:(线段树,STL,省队集训,省队集训,线段树,STL)