zoukankan      html  css  js  c++  java
  • [luogu]P1110 [ZJOI2007]报表统计

    原题链接:P1110 [ZJOI2007]报表统计

    题意

    题意是很简单的。。
    就是一开始有$n$个元素,每个元素相当于一个队列,总的序列是所有队列按顺序拼接起来的序列,有下面三种操作。
    操作一:在原序列第$k$个队列插入一个$x$
    操作二:查询总序列里面相邻元素的差值的绝对值的最小值。
    操作三:查询总序列里面所有元素差值的绝对值的最小值。

    分析

    第一个操作应该是建立在二,三操作的基础上进行的。。
    我们先对二,三操作进行讨论。

    第三个操作比较简单,我们只要建立一个平衡树,每次插入元素之后,查询这个元素和排名相邻的元素的差值,然后统计出最小值就可以了。

    重点是第二个操作。
    发现如果我们插入一个元素,这个元素会打破一对元素的相邻关系,并且建立两队相邻关系,每次的答案就是所有的相邻关系中差值最小的一对。
    差值最小的一对很容易用堆来维护,我们的问题就变成了维护一个可以删除的堆。

    这个堆也很容易实现。。
    我们开两个堆,第一个堆储存已经插入的数,第二个堆储存已经删除的数,每次弹出时我们只需要判断两堆的堆顶是不是一样,如果一样就同时弹掉,直到堆顶不一样。

    那么第一个操作就是这两个操作的结合了吧。。不讲了。。
    注意平衡树判断前驱,后继的时候要注意判断当前元素是否有多个,如果有多个的话说明最小值是零。

    同时有一个卡常小技巧。。
    最小值是一直向着$0$贴近的,不会变成负数也不会变大,所以当我们发现最小值变成$0$的时候,我们就不需要再进行平衡树操作了(卡了这个之后我代码快了700ms)。
    当然最开始的时候我们要对所有的数据进行初始化,确定每个数据在最终的数组中的位置。(不然用vector好像也是可以的,没试过,你们可以去试试) 

    下面就直接贴代码(常熟巨大不开氧气2336ms,开了氧气也是830ms)

    代码

      1 #include <bits/stdc++.h>
      2 #define fa(x) tree[x].fa
      3 #define son(x,k) tree[x].ch[k]
      4 #define cnt(x) tree[x].cnt
      5 #define val(x) tree[x].val
      6 #define siz(x) tree[x].siz
      7 using namespace std;
      8 const int N=5e6+1009;
      9 const int inf=(1<<31)-1;
     10 struct Hp{
     11     priority_queue<int>q1,q2;
     12     Hp(){
     13         while(!q1.empty())q1.pop();
     14         while(!q2.empty())q2.pop();
     15     }
     16     void Insert(int x){
     17         q1.push(-x);
     18     }
     19     void Delete(int x){
     20         q2.push(-x);
     21     }
     22     int Top(){
     23         while(!q2.empty()&&!q1.empty()){
     24             if(q1.top()!=q2.top())return -q1.top();
     25             q1.pop();q2.pop();
     26         }
     27     }
     28 }Heap;
     29 int read(){
     30     char c;int num,f=1;
     31     while(c=getchar(),!isdigit(c))if(c=='-')f=-1;num=c-'0';
     32     while(c=getchar(), isdigit(c))num=num*10+c-'0';
     33     return f*num;
     34 }
     35 int abs(int x){return x<0?-x:x;}
     36 int rt,tot;
     37 int n,m,pos[N],minn=(1<<31)-1;
     38 int ord[N][10],a[N],b[N];
     39 
     40 struct Node{
     41     int fa,ch[2],siz,cnt,val;
     42 }tree[N];
     43 bool chk(int x){return son(fa(x),1)==x;}
     44 void update(int x){siz(x)=siz(son(x,0))+siz(son(x,1))+cnt(x);}
     45 int New(int x,int pre){
     46     tot++;
     47     if(pre)son(pre,x>val(pre))=tot;
     48     son(tot,0)=son(tot,1)=0;
     49     cnt(tot)=siz(tot)=1;
     50     val(tot)=x;fa(tot)=pre;
     51     return tot;
     52 }
     53 void rotate(int x){
     54     int y=fa(x),z=fa(y),k=chk(x);
     55     son(z,chk(y))=x;fa(x)=z;
     56     son(y,k)=son(x,k^1);fa(son(x,k^1))=y;
     57     son(x,k^1)=y;fa(y)=x;
     58     update(y);update(x);
     59 }
     60 void splay(int x,int goal=0){
     61     while(fa(x)!=goal){
     62         int y=fa(x),z=fa(y);
     63         if(z!=goal){
     64             if(chk(y)==chk(x))rotate(y);
     65             else rotate(x);
     66         }
     67         rotate(x);
     68     }
     69     if(!goal)rt=x;
     70 }
     71 void Insert(int x){
     72     int cur=rt,p=0;
     73     while(cur&&val(cur)!=x)
     74         p=cur,cur=son(cur,x>val(cur));
     75     if(cur)cnt(cur)++;
     76     else cur=New(x,p);
     77     splay(cur);
     78 }
     79 void Find(int x){
     80     if(!rt)return ;
     81     int cur=rt;
     82     while(son(cur,x>val(cur))&&val(cur)!=x)
     83         cur=son(cur,x>val(cur));
     84     splay(cur);
     85 }
     86 int Pre(int x){
     87     Find(x);
     88     if(val(rt)<x||(val(rt)==x&&cnt(rt)>1))return rt;
     89     int cur=son(rt,0);
     90     while(son(cur,1))cur=son(cur,1);
     91     return cur;
     92 }
     93 int Succ(int x){
     94     Find(x);
     95     if(val(rt)>x||(val(rt)==x&&cnt(rt)>1))return rt;
     96     int cur=son(rt,1);
     97     while(son(cur,0))cur=son(cur,0);
     98     return cur;
     99 }
    100 int main()
    101 {
    102     n=read();m=read();
    103     Insert(inf);Insert(-inf);
    104     for(int i=1;i<=n;i++){
    105         int x=read();
    106         pos[i]=x;
    107         b[i]++;
    108     }
    109     for(int i=1;i<=m;i++){
    110         char c[19];
    111         scanf("%s",c);
    112         int len=strlen(c);
    113         if(len==6){
    114             ord[i][0]=1;
    115             ord[i][1]=read();
    116             ord[i][2]=read();
    117             b[ord[i][1]]++;
    118             ord[i][3]=b[ord[i][1]];
    119         }else if(len==7)ord[i][0]=2;
    120         else ord[i][0]=3;
    121     }
    122     for(int i=1;i<=n;i++){
    123         if(i!=1)Heap.Insert(abs(pos[i]-pos[i-1]));
    124         if(minn!=0){
    125             Insert(pos[i]);
    126             int xx=val(Succ(pos[i])),yy=val(Pre(pos[i]));
    127             if(xx!=inf&&xx!=-inf)minn=min(minn,xx-pos[i]);
    128             if(yy!=inf&&yy!=-inf)minn=min(minn,pos[i]-yy);
    129         }
    130         a[b[i-1]+1]=pos[i];
    131         //cout<<b[i-1]+1<<endl;
    132         b[i]+=b[i-1];
    133     }
    134     //cout<<Heap.Top()<<endl;
    135     for(int i=1;i<=m;i++){
    136         if(ord[i][0]==1){
    137             if(minn!=0) Insert(ord[i][2]);
    138             a[b[ord[i][1]-1]+ord[i][3]]=ord[i][2];
    139             
    140             Heap.Insert(abs(a[b[ord[i][1]-1]+ord[i][3]]-a[b[ord[i][1]-1]+ord[i][3]-1]));
    141             Heap.Insert(abs(a[b[ord[i][1]-1]+ord[i][3]]-a[b[ord[i][1]]+1]));
    142             Heap.Delete(abs(a[b[ord[i][1]]+1]-a[b[ord[i][1]-1]+ord[i][3]-1]));
    143             if(minn!=0){
    144                 int xx=val(Succ(ord[i][2])),yy=val(Pre(ord[i][2]));
    145                 if(xx!=inf&&xx!=-inf)minn=min(minn,xx-ord[i][2]);
    146                 if(yy!=inf&&yy!=-inf)minn=min(minn,ord[i][2]-yy);
    147             }
    148         }else if(ord[i][0]==2)
    149             printf("%d
    ",Heap.Top());
    150         else printf("%d
    ",minn);
    151     }
    152     return 0;
    153 }
    View Code
  • 相关阅读:
    Rman备份及不完全恢复操作
    win2003系统同步Linux ntp server批处理
    ntp服务器搭建
    notepad++调用python3中文乱码
    10G安装DataGuard
    oracle安装配置
    python之路(14)进程
    python之路(13)线程
    python之路(12)网络编程
    python之路(11)描述符
  • 原文地址:https://www.cnblogs.com/onglublog/p/10254559.html
Copyright © 2011-2022 走看看