UVALive 5902

UVALive 5902
Problem
  给一个元素总数为N的栈(stack<int>st)。起初栈顶到栈底元素为1,2,3,......,N。下面进行M次操作,每次从栈中取出一个数X(保证合法),问在X上面有多少个元素,且每次取出X后,把X放到栈顶。

Limits
Time Limit(ms): 3000
Memory Limit(MB): No Limit
N: [1,10^5]
M: [1,10^5]
X: [1,N]

Solution
  用一颗线段树Segment Tree,T(x) 表示x元素在栈中相对栈顶元素的位置,设栈顶元素位置为head,则第二个元素位置为head+1,依此类推。再用一个数组A,A[x] 表示x元素在线段树上的下标位置。起初,栈里元素为1,2,3,......,N;则A[X]为 P,P+1,......,P+N-1,其中P=1+M,P+N-1=N+M;线段树上 T(x)=x;每次操作,找到X元素在线段树上的权值T(x)=T(A[X]),表示X相对栈顶元素所在位置为T(x),则answer=T(x) - head,表示在X上面有 T(x) - head 个元素,输出answer。下面将X元素移到栈顶。在线段树上将下标从 A[X]+1 到 N+M 的权值全部减一;再将A[X]修改为head -1,然后head减一。循环进行如上M次操作。

More
为了更清楚阐述Solution,取如下例子并配图解释。
设N=8,M=5,M[x]={3,2,6,6,7};
起初,栈里元素X(x)={1,2,3,4,5,6,7,8};
申明一颗线段树,下标从1到N+M,即从1到13;线段树上T(x)=x;
开一个数组,A[x]={6,7,8,9,10,11,12,13};1所在线段树上的下标为6,8在13;
同时,head表示栈顶元素所在的位置,则head=6;
如下图所示:

第一步
M[1]=3,表示需要将X=3取出。T(x)=T(A[X])=T(8)=8;answer=T(x)-head=8-6=2;表示在X上面有2个元素(6和7);下面将3移到栈顶,把线段树上下标从 A[X]+1 到 N+M 的权值全部减一,即从 9 到 13再A[X]=head-1=5,head=head-1=5;表示3到了5这个位置,head也到了5这个位置。
如下图所示:

容易看出,1,2相对于head位置是6,7;而4-8相对于head位置是8-12;恰好在线段树上构成了5,6,7,......,11,12的相对位置。到了这,相信为什么要 “将线段树上下标从 A[x]+1 到 N+M 的权值全部减一”,就比较好理解了。
第二步
M[2]=2,X=2,T(x)=T(A[X])=T(7)=7;answer=T(x)-head=7-5=2;A[X]+1=8,N+M=13,从8到13权值减一;再A[X]=head-1=4,head=head-1=4;
如下图所示:

第三步
M[3]=6,X=6,T(x)=T(A[X])=T(11)=9;answer=T(x)-head=9-4=5;A[X]+1=12,N+M=13,从12到13权值减一;再A[X]=head-1=3,head=head-1=3;
如下图所示:

第四步
M[4]=6,X=6,T(x)=T(A[X])=T(3)=3;answer=T(x)-head=3-3=0;A[X]+1=4,N+M=13,从4到13权值减一;再A[X]=head-1=2,head=head-1=2;

第五步
M[5]=7,X=7,T(x)=T(A[X])=T(12)=8;answer=T(x)-head=8-2=6;A[X]+1=13,N+M=13,从13到13权值减一;再A[X]=head-1=1,head=head-1=1;
如下图所示:

演示结束。

容易发现以下几个性质。
一。线段树不方便处理下标为负数的情况,因此,一开始就将N个数“往后移位”。
二。T(x)上的值单调递增且不重复,是一个排列,完好地表示每个元素相对于head的位置。
三。A[x]与x的值高度一致,表示每一个元素所在线段树上的位置,保证了“将线段树上从from到to的位置减一”操作的正确性。
三。每次将线段树上从from到to的位置减一时,都只需令from=A[X]+1,to=N+M(最后的位置),而from之前的数恰好不需要处理。
四。每一步操作时间复杂度都为log级别,保证不超时。

Complexity
Time Complexity: O( (N+M)*log(N+M) )
Memory Complexity: O(4*(N+M) )

Source
UVALive 5902

Code
UVALive 5902 From My Github


你可能感兴趣的:(线段树,单点查询,区间更新,Constructive)