hdu_5818_Joint Stacks(线段树模拟)

题目链接:hdu_5818_Joint Stacks

题意:

给你两个栈,多了个合并操作,然后让你模拟

题解:

很容易想到O(1)的单个栈操作,O(n)的合并操作,这样肯定超时,所以我们要将时间复杂度均摊一下,让每个操作都是logn的,于是用上了线段树模拟。

线段树考虑染色,线段树的区间代表的是操作编号,0代表为A栈,1代表为B栈,每次merge 就把1到i这个区间染成指定颜色,然后pop就在线段树中找最右边的对应颜色的点。这样每次操作都是logn

不过官方题解给的是O(n)的解法,反正我是没想到的,感觉智商被压制。

第一份代码是线段树O(nlogn),第二份代码是数组模拟O(n)。也就只能快400ms

Joint Stacks

比较简单巧妙的一个做法是引入一个新的栈C,每次合并的时候就把A和B合并到C上,然后把A和B都清空. push还是按正常做,pop注意当遇到要pop的栈为空时,因为题目保证不会对空栈进行pop操作,所以这时应直接改为对C栈进行pop操作. 这样做因为保证每个元素最多只在一次合并中被处理到,pop和push操作当然也是每个元素只做一次,所以总复杂度是O(N)的. 另一种做法是用链表来直接模拟,复杂度也是O(N),但代码量稍大一些.

 1 #include<bits/stdc++.h>
 2 #define ls l,m,rt<<1
 3 #define rs m+1,r,rt<<1|1
 4 #define mst(a,b) memset(a,b,sizeof(a))
 5 #define F(i,a,b) for(int i=a;i<=b;++i)
 6 using namespace std;
 7 
 8 const int N=1e5+7;
 9 int n,tr[N<<2],lazy[N<<2],dt[N],now,ic=1;
10 char op[10],x[2],y[2];
11 
12 inline void pd(int rt)
13 {
14     if(lazy[rt])
15     {
16         if(tr[rt<<1])tr[rt<<1]=lazy[rt],lazy[rt<<1]=lazy[rt];
17         if(tr[rt<<1|1])tr[rt<<1|1]=lazy[rt],lazy[rt<<1|1]=lazy[rt];
18         lazy[rt]=0;
19     }
20 }
21 
22 void update(int L,int R,int c,int l=1,int r=n,int rt=1)
23 {
24     if(l==r&&L==R){tr[rt]=c;return;}
25     if(L<=l&&r<=R)
26     {
27         if(tr[rt])tr[rt]=c,lazy[rt]=c;
28         return;
29     }
30     pd(rt);
31     int m=(l+r)>>1;
32     if(L<=m)update(L,R,c,ls);
33     if(R>m)update(L,R,c,rs);
34     tr[rt]=tr[rt<<1]|tr[rt<<1|1];
35 }
36 
37 int pop(int x,int l=1,int r=n,int rt=1)
38 {
39     if(l==r){tr[rt]=0;return l;}
40     pd(rt);
41     int ans,m=(l+r)>>1;
42     if(tr[rt<<1|1]&x)ans=pop(x,rs);
43     else ans=pop(x,ls);
44     tr[rt]=tr[rt<<1]|tr[rt<<1|1];
45     return ans;
46 }
47 int main(){
48     while(scanf("%d",&n),n)
49     {
50         printf("Case #%d:
",ic++);
51         mst(tr,0),mst(lazy,0);
52         F(i,1,n)
53         {
54             scanf("%s",op);
55             if(op[0]=='p'&&op[1]=='u')
56             {
57                 scanf("%s%d",x,dt+i);
58                 if(x[0]=='A')update(i,i,1);else update(i,i,2);
59             }else if(op[0]=='p')
60             {
61                 scanf("%s",x);
62                 if(x[0]=='A')now=pop(1);else now=pop(2);
63                 printf("%d
",dt[now]);
64             }else
65             {
66                 scanf("%s%s",x,y);
67                 if(x[0]=='A')update(1,i,1);else update(1,i,2);
68             }
69         }
70     }
71     return 0;
72 }
View Code
 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;++i)
 3 using namespace std;
 4 typedef pair<int,int>P;
 5 
 6 const int N=5e4+7;
 7 int eda,edb,edc,n,tp,ic=1,c[N];
 8 char op[10],x[2],y[2];
 9 P a[N],b[N];
10 
11 int main()
12 {
13     while(scanf("%d",&n),n)
14     {
15         printf("Case #%d:
",ic++);
16         eda=edb=edc=0;
17         F(i,1,n)
18         {
19             scanf("%s",op);
20             if(op[0]=='p'&&op[1]=='u')
21             {
22                 scanf("%s%d",x,&tp);
23                 if(x[0]=='A')a[++eda].first=tp,a[eda].second=i;
24                 else b[++edb].first=tp,b[edb].second=i;
25             }else if(op[0]=='p')
26             {
27                 scanf("%s",x);
28                 if(x[0]=='A')
29                 {
30                     if(eda)printf("%d
",a[eda--].first);
31                     else printf("%d
",c[edc--]);
32                 }else
33                 {
34                     if(edb)printf("%d
",b[edb--].first);
35                     else printf("%d
",c[edc--]);
36                 }
37             }else
38             {
39                 scanf("%s%s",x,y);
40                 for(int ii=1,jj=1;ii<=eda||jj<=edb;)
41                     {
42                         if(ii<=eda&&jj<=edb)
43                         {
44                             if(a[ii].second<b[jj].second)c[++edc]=a[ii].first,ii++;
45                             else c[++edc]=b[jj].first,jj++;
46                         }else if(ii<=eda)c[++edc]=a[ii].first,ii++;
47                         else if(jj<=edb)c[++edc]=b[jj].first,jj++;
48                     }
49                 eda=0,edb=0;
50             }
51         }
52         
53     }
54     return 0;
55 }
View Code
原文地址:https://www.cnblogs.com/bin-gege/p/5756083.html