cjb-poi2010railway
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
{{{
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stack>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;++i)
#define mp make_pair
#define pb push_back
#define N 110000
int n,a[N],pos[N],b[N],c[N],col[N];
struct node1
{
int p[5*N];
void build(int t,int l,int r)
{
if (l==r){ p[t]=a[l]; return; }
int mid=(l+r)/2;
build(2*t,l,mid);
build(2*t+1,mid+1,r);
p[t]=max(p[2*t],p[2*t+1]);
}
int get(int t,int l,int r,int a,int b,int k)
{
if (l>r)return -1;
if (p[t]<=k)return -1;
if (l==r)return l;
int mid=(l+r)/2;
if (b<=mid)return get(2*t,l,mid,a,b,k);
if (a>mid)return get(2*t+1,mid+1,r,a,b,k);
int ans=get(2*t,l,mid,a,mid,k);
if (ans!=-1)return ans;
return get(2*t+1,mid+1,r,mid+1,b,k);
}
void del(int t,int l,int r,int k)
{
if (l==r){ p[t]=0; return; }
int mid=(l+r)/2;
if (k<=mid)del(2*t,l,mid,k);
else del(2*t+1,mid+1,r,k);
p[t]=max(p[2*t],p[2*t+1]);
}
}A;
struct node2
{
int p[5*N];
void build(int t,int l,int r)
{
if (l==r){ p[t]=pos[l]; return; }
int mid=(l+r)/2;
build(2*t,l,mid);
build(2*t+1,mid+1,r);
p[t]=min(p[2*t],p[2*t+1]);
}
int get(int t,int l,int r,int a,int b,int k)
{
if (l>r)return -1;
if (p[t]>=k)return -1;
if (l==r)return p[t];
int mid=(l+r)/2;
if (b<=mid)return get(2*t,l,mid,a,b,k);
if (a>mid)return get(2*t+1,mid+1,r,a,b,k);
int ans=get(2*t,l,mid,a,mid,k);
if (ans!=-1)return ans;
return get(2*t+1,mid+1,r,mid+1,b,k);
}
void del(int t,int l,int r,int k)
{
if (l==r){ p[t]=2147483647; return; }
int mid=(l+r)/2;
if (k<=mid)del(2*t,l,mid,k);
else del(2*t+1,mid+1,r,k);
p[t]=min(p[2*t],p[2*t+1]);
}
}B;
void dfs(int x,int cc)
{
//cout<<x<<endl;
col[x]=cc;
A.del(1,1,n,x);
B.del(1,1,n,a[x]);
while (1)
{
int p1=A.get(1,1,n,x+1,c[a[x]],a[x]);
if (p1!=-1)dfs(p1,((cc-1)^1)+1);
int p2=B.get(1,1,n,b[x]+1,a[x]-1,x);
if (p2!=-1)dfs(p2,((cc-1)^1)+1);
if (p1==-1 && p2==-1)break;
}
}
bool check()
{
stack<int> stack1,stack2;
while (!stack1.empty())stack1.pop();
while (!stack2.empty())stack2.pop();
int now=1;
rep(i,n)
{
int flag=0;
while (1)
{
if (!stack1.empty() && stack1.top()==i){ flag=1; stack1.pop(); break; }
if (!stack2.empty() && stack2.top()==i){ flag=1; stack2.pop(); break; }
if (now<=n && col[now]==1){ stack1.push(a[now++]); continue; }
if (now<=n && col[now]==2){ stack2.push(a[now++]); continue; }
if (now>n)break;
}
if (!flag)return 0;
}
return 1;
}
int main()
{
cin>>n;
rep(i,n){ scanf("%d",&a[i]); pos[a[i]]=i; }
A.build(1,1,n);
B.build(1,1,n);
b[n]=a[n]; for(int i=n-1;i>=1;i--)b[i]=min(b[i+1],a[i]);
rep(i,n)c[b[i]+1]=i; rep(i,n)c[i]=max(c[i-1],c[i]);
//rep(i,n)cout<<b[i]<<" "; puts("");
//rep(i,n)cout<<c[i]<<" "; puts("");
rep(i,n)col[i]=-1;
rep(i,n)if (col[i]==-1)dfs(i,1);
if (!check()){ puts("NIE"); return 0; }
puts("TAK");
rep(i,n)printf("%d%c",col[i],i==n?'\n':' ');
return 0;
}
}}}
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stack>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;++i)
#define mp make_pair
#define pb push_back
#define N 110000
int n,a[N],pos[N],b[N],c[N],col[N];
struct node1
{
int p[5*N];
void build(int t,int l,int r)
{
if (l==r){ p[t]=a[l]; return; }
int mid=(l+r)/2;
build(2*t,l,mid);
build(2*t+1,mid+1,r);
p[t]=max(p[2*t],p[2*t+1]);
}
int get(int t,int l,int r,int a,int b,int k)
{
if (l>r)return -1;
if (p[t]<=k)return -1;
if (l==r)return l;
int mid=(l+r)/2;
if (b<=mid)return get(2*t,l,mid,a,b,k);
if (a>mid)return get(2*t+1,mid+1,r,a,b,k);
int ans=get(2*t,l,mid,a,mid,k);
if (ans!=-1)return ans;
return get(2*t+1,mid+1,r,mid+1,b,k);
}
void del(int t,int l,int r,int k)
{
if (l==r){ p[t]=0; return; }
int mid=(l+r)/2;
if (k<=mid)del(2*t,l,mid,k);
else del(2*t+1,mid+1,r,k);
p[t]=max(p[2*t],p[2*t+1]);
}
}A;
struct node2
{
int p[5*N];
void build(int t,int l,int r)
{
if (l==r){ p[t]=pos[l]; return; }
int mid=(l+r)/2;
build(2*t,l,mid);
build(2*t+1,mid+1,r);
p[t]=min(p[2*t],p[2*t+1]);
}
int get(int t,int l,int r,int a,int b,int k)
{
if (l>r)return -1;
if (p[t]>=k)return -1;
if (l==r)return p[t];
int mid=(l+r)/2;
if (b<=mid)return get(2*t,l,mid,a,b,k);
if (a>mid)return get(2*t+1,mid+1,r,a,b,k);
int ans=get(2*t,l,mid,a,mid,k);
if (ans!=-1)return ans;
return get(2*t+1,mid+1,r,mid+1,b,k);
}
void del(int t,int l,int r,int k)
{
if (l==r){ p[t]=2147483647; return; }
int mid=(l+r)/2;
if (k<=mid)del(2*t,l,mid,k);
else del(2*t+1,mid+1,r,k);
p[t]=min(p[2*t],p[2*t+1]);
}
}B;
void dfs(int x,int cc)
{
//cout<<x<<endl;
col[x]=cc;
A.del(1,1,n,x);
B.del(1,1,n,a[x]);
while (1)
{
int p1=A.get(1,1,n,x+1,c[a[x]],a[x]);
if (p1!=-1)dfs(p1,((cc-1)^1)+1);
int p2=B.get(1,1,n,b[x]+1,a[x]-1,x);
if (p2!=-1)dfs(p2,((cc-1)^1)+1);
if (p1==-1 && p2==-1)break;
}
}
bool check()
{
stack<int> stack1,stack2;
while (!stack1.empty())stack1.pop();
while (!stack2.empty())stack2.pop();
int now=1;
rep(i,n)
{
int flag=0;
while (1)
{
if (!stack1.empty() && stack1.top()==i){ flag=1; stack1.pop(); break; }
if (!stack2.empty() && stack2.top()==i){ flag=1; stack2.pop(); break; }
if (now<=n && col[now]==1){ stack1.push(a[now++]); continue; }
if (now<=n && col[now]==2){ stack2.push(a[now++]); continue; }
if (now>n)break;
}
if (!flag)return 0;
}
return 1;
}
int main()
{
cin>>n;
rep(i,n){ scanf("%d",&a[i]); pos[a[i]]=i; }
A.build(1,1,n);
B.build(1,1,n);
b[n]=a[n]; for(int i=n-1;i>=1;i--)b[i]=min(b[i+1],a[i]);
rep(i,n)c[b[i]+1]=i; rep(i,n)c[i]=max(c[i-1],c[i]);
//rep(i,n)cout<<b[i]<<" "; puts("");
//rep(i,n)cout<<c[i]<<" "; puts("");
rep(i,n)col[i]=-1;
rep(i,n)if (col[i]==-1)dfs(i,1);
if (!check()){ puts("NIE"); return 0; }
puts("TAK");
rep(i,n)printf("%d%c",col[i],i==n?'\n':' ');
return 0;
}