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

      如果算上调stl的话这题似乎有很多种做法。。。调set、map,敲线段树、spaly。。blabla

      完美地避开了正解TAT

      题目要求维护一坨数,能够随时插入,查询相邻的数的最小差值,查询任意两数间的最小差值。

      第二问比较好写,然而人太弱不会调set。。于是写了个treap。。每次插入后查询一下前驱和后继更新一下答案。然后这个答案显然是递减的,所以数列中有相同的数之后就不用理了(大概就是市面上各种spaly能够卡时16s+过的原因。。。。)。

      然而第一问就没法用treap做了。。把原数列存在map[]里面。

      假设是在原数列第pos个元素后插入一个数x,那么x的右边的那个数就是map[pos+1](如果pos<n的话)

      x左边的那个数其实就是本来第pos个元素后面插了一坨数的最后一个,用last[i]表示当前(插入x之前)第i个元素后面插进去的一坨数的最后一个数的大小。

      所以把x插进去后,原先的差值abs(last[pos]-map[pos+1])不存在了,新增了两个差值为abs(last[pos]-x)和abs(x-map[pos+1])

      用优先队列(堆)维护下差值就好了。。。。。

      具体姿势:

        对于新增的差值abs(last[pos]-x),它是不会被新增的数影响的。。然而abs(x-map[pos+1])可能因为之后在x后面插进去新的数而不存在。。。

        判断这个差值存不存在就看x是不是所在元素的最后一次插入的数。每次查询的时候先把队头(小根堆顶)那些不存在的差值弹掉就行了。

    事实证明这样写主要时间复杂度是在treap上= =。。。优先队列的速度比treap高明到不知道哪里去了。。treap的速度又比spaly高明到不知道哪里去了。。。

    跑了7s+。。。。并不算快TAT

    发现大部分的时间都是在treap建树的时候。。。所以直接把数列排序后递归建树(参见spaly建树姿势)就2028ms过了。。。速度#5。。

    感觉第一问调set才是拯救常数的正确姿势= =

    改了点细节然后1980ms#3。。。。。#1丧心病狂甩别人若干条街

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<queue>
     5 #include<algorithm>
     6 #include<cstdlib>
     7 using namespace std;
     8 const int maxn=1000003;
     9 const int inf=1002333333;
    10 struct zs{
    11     int pos,len,val;
    12 };
    13 int num[maxn],rnd[maxn],l[maxn],r[maxn],last[maxn>>1],map[maxn>>1],len[maxn>>1];
    14 int i,j,n,m,minsg,ming,tot,rt,x,a,b,aft,pre;
    15 priority_queue<zs>q;
    16 bool operator <(zs a,zs b){return a.val>b.val;}
    17 int ra,fh;char rx;
    18 inline int read(){
    19     rx=getchar();ra=0;fh=1;
    20     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
    21     if(rx=='-')fh=-1,rx=getchar();
    22     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
    23 }
    24 char s[11];
    25 inline void outx(int x){
    26     while(x>0||!s[0])s[++s[0]]=x%10,x/=10;
    27     while(s[0])putchar(s[s[0]--]+48);putchar('
    ');
    28 }
    29 inline void lturn(int &x,int R){r[x]=l[R],l[R]=x,x=R;}
    30 inline void rturn(int &x,int L){l[x]=r[L],r[L]=x,x=L;}
    31 void ins(int &x,int val){
    32     if(!x){x=++tot,num[x]=val,rnd[x]=rand();return;}
    33     if(val<num[x]){
    34         ins(l[x],val);
    35         if(rnd[l[x]]<rnd[x])rturn(x,l[x]);
    36     }else if(val>num[x]){
    37         ins(r[x],val);
    38         if(rnd[r[x]]<rnd[x])lturn(x,r[x]);
    39     }else minsg=0;
    40 }
    41 void getpre(int now,int val){
    42     if(!now)return;
    43     if(num[now]>val)getpre(l[now],val);
    44     else pre=num[now],getpre(r[now],val);
    45 }
    46 void getaft(int now,int val){
    47     if(!now)return;
    48     if(num[now]<val)getaft(r[now],val);
    49     else aft=num[now],getaft(l[now],val);
    50 }
    51 inline void insert(int p,int x){
    52     if(minsg>0)pre=-inf,aft=inf,getpre(rt,x),getaft(rt,x),minsg=min(minsg,min(x-pre,aft-x));
    53     if(minsg>0)ins(rt,x);
    54     ming=min(ming,abs(last[p]-x));
    55     len[p]++;last[p]=x;
    56     if(p<n&&ming>0)q.push((zs){ p,len[p],abs(map[p+1]-x) });
    57 }
    58 void build(int L,int R,int &now,int farnd){
    59     if(L>R)return;
    60     int mid=(L+R+1)>>1;
    61     now=++tot,num[now]=map[mid],rnd[now]=farnd+23333;
    62     build(L,mid-1,l[now],rnd[now]);build(mid+1,R,r[now],rnd[now]);
    63 }
    64 int main(){
    65     n=read();m=read();
    66     minsg=ming=inf;
    67     for(i=1;i<=n;i++)last[i]=map[i]=read();
    68     sort(map+1,map+1+n),rt=(n+1)>>1,build(1,n,rt,0);
    69     for(i=1;i<n;i++)minsg=min(minsg,map[i+1]-map[i]);
    70     for(i=1;i<n;i++)len[i]=1,q.push((zs){ i,len[i],abs(last[i]-last[i+1]) });
    71     memcpy(map,last,(n+1)<<2);
    72     char ch1;
    73     while(m--){
    74         for(ch1=getchar();ch1<'A'||ch1>'Z';ch1=getchar());
    75         if(ch1=='I')
    76             a=read(),b=read(),insert(a,b);
    77         else{
    78             ch1=getchar(),ch1=getchar(),ch1=getchar(),ch1=getchar();
    79             if(ch1=='S')outx(minsg);
    80             else{
    81                 while(q.top().len!=len[q.top().pos])q.pop();
    82                 outx(min(ming,q.top().val));
    83             }
    84             while(ch1!='P')ch1=getchar();
    85         }
    86     }
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    string的erase函数和find、find_first_of函数
    strtok和strtok_r
    Linux添加硬盘 挂载硬盘(附 Linux磁盘挂载和mount共享 带图)
    linux下访问中文目录文件
    用yield写协程实现生产者消费者
    用进程池和线程池实现高并发服务器
    python自带线程池
    python自带进程池
    模拟线程池代码
    面向对象的多次调用线程(含参版)
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5100348.html
Copyright © 2011-2022 走看看