• 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
  • 相关阅读:
    专利申请流程
    安装Fedora16与Windows7共存双系统
    rpm检查依赖性
    C++中的static函数和extern关键字
    asp.net 浏览服务器文件
    如何用批处理文件写:获取当前日期的前一天
    有一个无效 SelectedValue,因为它不在项目列表中。
    .net 4.0 检测到有潜在危险的 Request.Form 值。
    ckeditor 在C#中使用
    使用任务计划程序自动执行任务
  • 原文地址:https://www.cnblogs.com/bin-gege/p/5756083.html
Copyright © 2020-2023  润新知