zoukankan      html  css  js  c++  java
  • 【HDU4967】Handling the Past

    题意

       模拟栈操作。有三种操作push,pop,peak分别代表从栈顶压入元素,删除栈顶元素,查询栈顶元素。但是,每个操作会给出一个时间戳,要求操作必须要按照时间戳来进行。但是对于每个peak必须马上给出查询结果。其中n<=50000,xi,ti<=1e9

    分析

      讲真,这种题必须结合样例才能明白让干嘛。如果暴力的话,对于每个peak的时间复杂度都是O(n)。所以我们想到了线段树。

      1.因为t的值很大,所以我们要首先将t离散化(我因为离散化写丑了一开始还T了好几发)

      2.将每个push的t和x对应的记录下来

      3.对于每个操作push,我们在t的位置插入1,对于每个pop操作,我们在t的位置插入-1。对于每个peak操作,我们找到t左边的第一个t1,符合sum(t1 to t)>0,这时候和t1对应的x值就是答案。

    思路是很好想的,然后就是操作3该怎么通过线段树来维护?

      我们通过线段树来维护一个区间和,和一个最大后缀和,然后对于没个peak查询,所有从1到t的线段树的结点,从右往左找,如果加上当前结点的最大后缀和大于0的话,这个答案就一定在这个节点内,否则加上这个结点的区间和继续往左找。这里可以结合代码进行理解。

      

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <map>
      7 
      8 using namespace std;
      9 const int maxn=50000+100;
     10 struct Ope{
     11     string name;
     12     int t,a;
     13 }ope[maxn];
     14 int n,kase;
     15 int V[maxn],M[maxn];
     16 int sumv[4*maxn],max_suff[4*maxn];
     17 int v,x;
     18 void maintain(int o){
     19     sumv[o]=sumv[2*o]+sumv[2*o+1];
     20     max_suff[o]=max(max_suff[2*o+1],sumv[2*o+1]+max_suff[2*o]);
     21 }
     22 void update(int o,int L,int R){
     23     if(L==R){
     24         sumv[o]+=x;
     25         max_suff[o]+=x;
     26         return ;
     27     }
     28     int M=L+(R-L)/2;
     29     if(v<=M)update(2*o,L,M);
     30     if(v>M)update(2*o+1,M+1,R);
     31     maintain(o);
     32     return;
     33 }
     34 int tot,ans;
     35 int ql,qr;
     36 void solve(int o,int L,int R){
     37     if(L==R){
     38         ans=L;
     39         return;
     40     }
     41     int M=L+(R-L)/2;
     42     if(tot+max_suff[2*o+1]>0)
     43       return solve(2*o+1,M+1,R);
     44     tot+=sumv[2*o+1];
     45     return solve(2*o,L,M);
     46 }
     47 void query(int o,int L,int R){
     48     if(ans!=-1)
     49         return;
     50     if(ql<=L&&qr>=R){
     51         if(tot+max_suff[o]>0){
     52             solve(o,L,R);
     53         }
     54         else tot+=sumv[o];
     55         return;
     56     }
     57     int M=L+(R-L)/2;
     58     if(M<qr)
     59         query(2*o+1,M+1,R);
     60     if(M>=ql)
     61         query(2*o,L,M);
     62     return;
     63 }
     64 int main(){
     65     kase=0;
     66     while(scanf("%d",&n)!=EOF&&n){
     67         printf("Case #%d:
    ",++kase);
     68         for(int i=1;i<=n;i++){
     69             cin>>ope[i].name;
     70             if(ope[i].name=="push"){
     71                 scanf("%d%d",&ope[i].a,&ope[i].t);
     72             }
     73             if(ope[i].name=="pop"||ope[i].name=="peak"){
     74                 scanf("%d",&ope[i].t);
     75             }
     76             V[i]=ope[i].t;
     77         }
     78         sort(V+1,V+1+n);
     79         for(int i=1;i<=n;i++){
     80             if(ope[i].name=="push"){
     81                 int tt=lower_bound(V+1,V+1+n,ope[i].t)-V;
     82                 M[tt]=ope[i].a;
     83             }
     84         }
     85        /* for(int i=1;i<=n;i++){
     86             int tt=lower_bound(V+1,V+1+n,ope[i].t)-V;
     87             cout<<tt<<endl;
     88         }*/
     89 
     90         memset(sumv,0,sizeof(sumv));
     91         memset(max_suff,0,sizeof(max_suff));
     92 
     93         for(int i=1;i<=n;i++){
     94             if(ope[i].name=="push"){
     95                 v=lower_bound(V+1,V+1+n,ope[i].t)-V;
     96                 x=1;
     97                 update(1,1,n);
     98             }
     99             else if(ope[i].name=="pop"){
    100                 v=lower_bound(V+1,V+1+n,ope[i].t)-V;
    101                 x=-1;
    102                 update(1,1,n);
    103             }
    104             else{
    105                 ql=1,qr=lower_bound(V+1,V+1+n,ope[i].t)-V;
    106                 tot=0,ans=-1;
    107                 query(1,1,n);
    108                 printf("%d
    ",ans==-1?-1:M[ans]);
    109             }
    110         }
    111     }
    112 return 0;
    113 }
    View Code
  • 相关阅读:
    求字符串中最大的递增子序列
    分析函数改写自关联
    收集统计信息让SQL走正确的执行计划
    利用case when 减少表扫描次数
    利用查询提示优化SQL
    利用SQL进行推理
    查找字段连续相同的最大值
    优化有标量子查询的SQL
    将部分相同的多行记录转成一行多列
    .net 测试工具类
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9011681.html
Copyright © 2011-2022 走看看