• ZJOI2007报表统计·BZOJ1058


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1058

    1058: [ZJOI2007]报表统计

    Time Limit: 15 Sec  Memory Limit: 162 MB

    Description

    小 Q的妈妈是一个出纳,经常需要做一些统计报表的工作。今天是妈妈的生日,小Q希望可以帮妈妈分担一些工作,作为她的生日礼物之一。经过仔细观察,小Q发现 统计一张报表实际上是维护一个非负整数数列,并且进行一些查询操作。在最开始的时候,有一个长度为N的整数序列,并且有以下三种操作: INSERT i k 在原数列的第i个元素后面添加一个新元素k; 如果原数列的第i个元素已经添加了若干元素,则添加在这些元素的最后(见下面的例子) MIN_GAP 查询相邻两个元素的之间差值(绝对值)的最小值 MIN_SORT_GAP 查询所有元素中最接近的两个元素的差值(绝对值) 例如一开始的序列为 5 3 1 执行操作INSERT 2 9将得到: 5 3 9 1 此时MIN_GAP为2,MIN_SORT_GAP为2。 再执行操作INSERT 2 6将得到: 5 3 9 6 1 注意这个时候原序列的第2个元素后面已经添加了一个9,此时添加的6应加在9的后面。这个时候MIN_GAP为2,MIN_SORT_GAP为1。于是小 Q写了一个程序,使得程序可以自动完成这些操作,但是他发现对于一些大的报表他的程序运行得很慢,你能帮助他改进程序么?

    Input

    第一行包含两个整数N,M,分别表示原数列的长度以及操作的次数。第二行为N个整数,为初始序列。接下来的M行每行一个操作,即“INSERT i k”,“MIN_GAP”,“MIN_SORT_GAP”中的一种(无多余空格或者空行)。

    Output

    对于每一个“MIN_GAP”和“MIN_SORT_GAP”命令,输出一行答案即可。

    Sample Input

    3 5
    5 3 1
    INSERT 2 9
    MIN_SORT_GAP
    INSERT 2 6
    MIN_GAP
    MIN_SORT_GAP

    Sample Output

    2
    2
    1

    HINT

    对于30%的数据,N ≤ 1000 , M ≤ 5000 对于100%的数据,N , M ≤500000 对于所有的数据,序列内的整数不超过5*108。

    卧槽。。这题真TM恶心。。我从上午改到现在。。原因是TLE。。(妈蛋我要不是抱着试一试的心情交了这次我都不知道我特么AC了。。)在下面测,最慢的要2s多。。就不敢交

    不过第一个版本的动态插入式的还是TLE。。优化的版本是直接Build树。。没什么好说的。。TTTTTTTTTTTTT________________TTTTTTTTTTTTT...

    Codes:

      1 #include<set>
      2 #include<queue>
      3 #include<vector>
      4 #include<cstdio>
      5 #include<cstdlib>
      6 #include<cstring>
      7 #include<iostream>
      8 #include<algorithm>
      9 using namespace std;
     10 const int N = 500010;
     11 #define Sets(T,a,b,c){T[a].s[c] = b; T[b].p = a;}
     12 #define rep(i,n) for(int i=1;i<=n;i++)
     13 #define For(i,l,r) for(int i=l;i<=r;i++)
     14 
     15 struct tnode{
     16     int s[2],v,p,num;
     17 }T1[N<<1],T2[N<<1];
     18 
     19 int kth,val,A[N],Last[N],MSG=2147483647,n,m;
     20 int cnt,root1,root2,tot1,tot2,y,z;
     21 
     22 int read(){
     23     int num = 0; char ch = getchar();
     24     int q = 0;
     25     while(ch<'0'||ch>'9') {
     26         if(ch=='-') q = 1;
     27         ch = getchar();
     28     }
     29     while(ch>='0'&&ch<='9'){
     30         num = num * 10 + ch-'0';
     31         ch = getchar();
     32     }
     33     return (q==1)?(-num):num;
     34 }
     35 
     36 void Rot(tnode T[],int x){
     37     //cnt++;
     38     int y = T[x].p , z = T[y].p;
     39     int lx = T[y].s[1] == x , ly = T[z].s[1] == y;
     40     Sets(T,y,T[x].s[!lx],lx);
     41     Sets(T,z,x,ly);
     42     Sets(T,x,y,lx^1);
     43 }
     44 
     45 void Splay(tnode T[],int i,int goal,int &root){
     46     while(T[i].p!=goal){
     47         if(T[T[i].p].p!=goal) Rot(T,T[i].p);
     48         Rot(T,i);
     49     }
     50     if(!goal) root = i;
     51 }
     52 
     53 void Insert_1(int V,int i){
     54     if(!i){
     55         root1 = ++tot1;T1[root1].num = 1;T1[root1].p = 0;T1[root1].v = V;
     56         return;
     57     }
     58     MSG = min(MSG,abs(V-T1[i].v));
     59     if(T1[i].v==V)   T1[i].num++;
     60     else{
     61         if(!T1[i].s[V>T1[i].v]){
     62             T1[i].s[V>T1[i].v] = ++tot1;T1[tot1].p = i;T1[tot1].v = V; T1[tot1].num = 1;
     63             Splay(T1,tot1,0,root1);
     64         }
     65         else Insert_1(V,T1[i].s[V>T1[i].v]);
     66     }
     67 }
     68 
     69 void Insert_2(int V,int i){
     70     if(!i){
     71         root2 = ++tot2;T2[root2].num = 1;T2[root2].p = 0;T2[root2].v = V;
     72         return;
     73     }
     74     if(T2[i].v==V)   T2[i].num++;
     75     else{
     76         if(!T2[i].s[V>T2[i].v]){
     77             T2[i].s[V>T2[i].v] = ++tot2;T2[tot2].p = i;T2[tot2].v = V; T2[tot2].num = 1;
     78             Splay(T2,tot2,0,root2);
     79         }
     80         else Insert_2(V,T2[i].s[V>T2[i].v]);
     81     }
     82 }
     83 
     84 int prev(int i){
     85     int Next = T2[i].s[0];
     86     while(T2[Next].s[1]) Next = T2[Next].s[1];
     87     return Next;
     88 }
     89 
     90 void Delete(int i){
     91     if(T2[i].num>1) {
     92         T2[i].num--;
     93         return;
     94     }
     95     Splay(T2,i,0,root2);
     96     if(T2[i].s[0]){
     97         Splay(T2,prev(i),i,root2);
     98         Sets(T2,T2[i].s[0],T2[i].s[1],1);
     99         T2[T2[i].s[0]].p = 0;
    100         root2 = T2[i].s[0];
    101     }else{
    102         if(T2[i].s[1]){root2 = T2[i].s[1];T2[T2[i].s[1]].p = 0;}
    103         else           root2 = 0;
    104     }
    105     T2[i].num = T2[i].p = T2[i].s[0] = T2[i].s[1] = T2[i].v = 0;
    106 }
    107 
    108 int Min(int root2){
    109     int Next = T2[root2].s[0];
    110     if(!Next) return T2[root2].v;
    111     while(T2[Next].s[0]) Next =T2[Next].s[0];
    112     return T2[Next].v;
    113 }
    114 
    115 int find(int V,int i){
    116     if(V==T2[i].v) return i;
    117     else           return find(V,T2[i].s[V>T2[i].v]);
    118 }
    119 
    120 void Build1(int l,int r,int &i,int p){
    121     if(l>r) return;
    122     int m = (l+r) >> 1;
    123     T1[i=++tot1].p = p; T1[i].v = A[m]; T1[i].num++;
    124     Build1(l,m-1,T1[i].s[0],i);
    125     Build1(m+1,r,T1[i].s[1],i);
    126 }
    127 
    128 void Build2(int l,int r,int &i,int p){
    129     if(l>r) return;
    130     int m = (l+r) >> 1;
    131     T2[i=++tot2].p = p; T2[i].v = Last[m];T2[i].num++;
    132     Build2(l,m-1,T2[i].s[0],i);
    133     Build2(m+1,r,T2[i].s[1],i);
    134 }
    135 
    136 int main(){
    137     //freopen("form.in","r",stdin);
    138     //freopen("form.out","w",stdout);
    139     n = read(); m = read();
    140     rep(i,n){
    141         A[i] = read();
    142         //Insert_1(A[i],root1);
    143        // if(i>1) Insert_2(abs(A[i]-A[i-1]),root2);
    144         //Last[i] = A[i];
    145         if(i>1) Last[i-1] = abs(A[i] - A[i-1]);
    146     }
    147     sort(Last+1,Last+n);
    148     Build2(1,n-1,root2,0);
    149     rep(i,n) Last[i] = A[i];
    150     sort(A+1,A+n+1);For(i,1,n-1) MSG=min(MSG,abs(A[i]-A[i+1]));
    151     Build1(1,n,root1,0);
    152     rep(i,n) A[i] = Last[i]; 
    153     char op[20];int troot;
    154     rep(i,m){
    155         scanf("%s",&op);
    156         if(op[0]=='I'){
    157             kth = read() , val = read();
    158             if(kth<n) {
    159                 troot = find(abs(Last[kth]-A[kth+1]),root2);
    160                 Delete(troot);
    161             }
    162             Insert_2(abs(val-Last[kth]),root2);
    163             if(kth<n) Insert_2(abs(val-A[kth+1]),root2);
    164             Insert_1(val,root1);
    165             Last[kth] = val;
    166             continue;
    167         }
    168         if(op[4]=='S') printf("%d
    ",MSG);
    169         if(op[4]=='G') printf("%d
    ",Min(root2));
    170     }
    171     //printf("%d
    ",cnt);
    172     return 0;
    173 }

    好长。。T___T。。好像还没说做法,我sb地建了两棵平衡树。。一棵维护MIN_GAP 一棵维护MIN_SORT_GAP。。

    实际上,可以用堆维护MIN_GAP。。或者是Set。。

  • 相关阅读:
    《P3953 [NOIP2017 提高组] 逛公园》
    《P4180 [BJWC2010]严格次小生成树》
    《济南icpc补题》
    《levil的因子和》
    《洛谷P2704 [NOI2001]炮兵阵地》
    《Codeforces Round #689 (Div. 2, based on Zed Code Competition)》
    《2174: Leapin' Lizards》
    《3820: Revenge of Fibonacci 》
    马拉车求最长回文子串
    二分训练
  • 原文地址:https://www.cnblogs.com/zjdx1998/p/3861274.html
Copyright © 2020-2023  润新知