zoukankan      html  css  js  c++  java
  • BZOJ 3524: [Poi2014]Couriers 主席树

       这道题直接在我上一篇博客的代码的基础上改的。再一次地证明了 read() 读入是要比 scanf 快的事实,没加read(),跑了5400毫秒,加了之后,跑了4600毫秒,再加个 inline 又快了300毫秒。 最终4384毫秒跑完此题。加油。 (不过一开始因为是改的,RE了一次,以后要小心啊!)

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #define rep(i,j,k) for(int i = j; i <= k; i++)
     5 using namespace std;
     6 int root[500005], a[500005], p[500005];
     7 int n_nodes = 0, n_numb;
     8 
     9 inline int read()
    10 {
    11     int s = 0, t = 1; char c = getchar();
    12     while( !isdigit(c) ){
    13         if( c == '-' ) t = -1; c = getchar();
    14     }
    15     while( isdigit(c) ){
    16         s = s * 10 + c - '0'; c = getchar();
    17     }
    18     return s * t;
    19 }
    20 
    21 struct node{
    22 int times, lc, rc;
    23 } nod[10000000];
    24 
    25 void build(int l,int r,int&p){
    26     p = ++n_nodes;
    27     nod[p].lc = nod[p].rc = nod[p].times = 0;
    28     if( l >= r ) return;
    29     int mid = (l+r)/2;
    30     build(l,mid,nod[p].lc); build(mid+1,r,nod[p].rc);
    31 }
    32 
    33 void build2(int l,int r,int&p, int pre,int mre)
    34 {
    35     p = ++n_nodes;
    36     nod[p] = nod[pre];
    37     nod[p].times++;
    38     if( l >= r ) return;
    39     int mid = (l+r)/2;
    40     if( mre <= mid ){
    41         build2(l,mid,nod[p].lc,nod[pre].lc,mre);
    42     }    
    43     else {
    44         build2(mid+1,r,nod[p].rc,nod[pre].rc,mre);
    45     }
    46 }
    47 
    48 int ask(int l,int r,int pre,int p,int k)
    49 {
    50     if( nod[p].times - nod[pre].times <= k ) return -1;
    51     if( l >= r ) return l;
    52     int sl = nod[nod[p].lc].times - nod[nod[pre].lc].times;
    53     int mid = (l+r) / 2;
    54     if( sl > k ){
    55         return ask(l,mid,nod[pre].lc,nod[p].lc,k);
    56     }
    57     else{
    58         return ask(mid+1,r,nod[pre].rc,nod[p].rc,k);
    59     }
    60 }
    61 
    62 int main()
    63 {
    64     int n = read(), q = read();
    65     rep(i,1,n){
    66         p[i] = a[i] = read();
    67     }
    68     sort(p+1,p+1+n);
    69     n_numb = unique(p+1,p+1+n) - p - 1;
    70     build(1,n_numb,root[0]);
    71     rep(i,1,n){
    72         int m = lower_bound(p+1,p+n_numb+1,a[i]) - p;
    73         build2(1,n_numb,root[i],root[i-1],m);
    74     }
    75     rep(i,1,q){
    76         int x = read(), y = read();
    77         int k = (y-x+1)/2;
    78         int m = ask(1,n_numb,root[x-1],root[y],k);
    79         if( m == -1 ) printf("%d
    ", 0);
    80         else printf("%d
    ", p[m]);
    81     }
    82     return 0;
    83 }

    这是指针版的,又快了100多毫秒(指针要传引用的)

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #define rep(i,j,k) for(int i = j; i <= k; i++)
     5 using namespace std;
     6 int a[500005], p[500005];
     7 int n_nodes = 0, n_numb;
     8  
     9 inline int read()
    10 {
    11     int s = 0, t = 1; char c = getchar();
    12     while( !isdigit(c) ){
    13         if( c == '-' ) t = -1; c = getchar();
    14     }
    15     while( isdigit(c) ){
    16         s = s * 10 + c - '0'; c = getchar();
    17     }
    18     return s * t;
    19 }
    20  
    21 struct node{
    22 int times;
    23 node* lc, *rc;
    24 } nod[10000000];
    25 node* root[500005], *pt;
    26 
    27 void build(int l,int r,node*&p){
    28     p = ++pt;
    29     p->lc = p->rc = NULL; pt->times = 0;
    30     if( l >= r ) return;
    31     int mid = (l+r)/2;
    32     build(l,mid,p->lc); build(mid+1,r,p->rc);
    33 }
    34  
    35 void build2(int l,int r,node*&p, node*pre,int mre)
    36 {
    37     p = ++pt; 
    38     *p = *pre; p->times++;
    39     if( l >= r ) return;
    40     int mid = (l+r)/2;
    41     if( mre <= mid ){
    42         build2(l,mid,p->lc,pre->lc,mre);
    43     }   
    44     else {
    45         build2(mid+1,r,p->rc,pre->rc,mre);
    46     }
    47 }
    48  
    49 int ask(int l,int r,node* pre,node* p,int k)
    50 {
    51     if( p->times - pre->times <= k ) return -1;
    52     if( l >= r ) return l;
    53     int sl = p->lc->times - pre->lc->times;
    54     int mid = (l+r) / 2;
    55     if( sl > k ){
    56         return ask(l,mid,pre->lc,p->lc,k);
    57     }
    58     else{
    59         return ask(mid+1,r,pre->rc,p->rc,k);
    60     }
    61 }
    62  
    63 int main()
    64 {
    65     int n = read(), q = read(); pt = nod;
    66     rep(i,1,n){
    67         p[i] = a[i] = read();
    68     }
    69     sort(p+1,p+1+n);
    70     n_numb = unique(p+1,p+1+n) - p - 1;
    71     build(1,n_numb,root[0]);
    72     rep(i,1,n){
    73         int m = lower_bound(p+1,p+n_numb+1,a[i]) - p;
    74         build2(1,n_numb,root[i],root[i-1],m);
    75     }
    76     rep(i,1,q){
    77         int x = read(), y = read();
    78         int k = (y-x+1)/2;
    79         int m = ask(1,n_numb,root[x-1],root[y],k);
    80         if( m == -1 ) printf("%d
    ", 0);
    81         else printf("%d
    ", p[m]);
    82     }
    83     return 0;
    84 }

    3524: [Poi2014]Couriers

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 1004  Solved: 350
    [Submit][Status][Discuss]

    Description

    给一个长度为n的序列a。1≤a[i]≤n。
    m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。

    Input

    第一行两个数n,m。
    第二行n个数,a[i]。
    接下来m行,每行两个数l,r,表示询问[l,r]这个区间。

    Output

    m行,每行对应一个答案。

    Sample Input

    7 5
    1 1 3 2 3 4 3
    1 3
    1 4
    3 7
    1 7
    6 6

    Sample Output

    1
    0
    3
    0
    4

    HINT

    【数据范围】

    n,m≤500000

    人一我十,人十我万!追逐青春的梦想,怀着自信的心,永不放弃!仿佛已看到希望,尽管还在远方
  • 相关阅读:
    js--数组中的最值
    js--数组合并并且去重
    js---数组去重的方法总结???
    input 输入框又被输入法遮挡啦
    使用装饰者模式改善既有代码
    简易的 webpack + vue 完成本地化数据 mock
    vue 数据持久化(刷新保存数据)的探索
    JavaScript await 与 promise 的纠葛
    javascript 函数的暂停和恢复
    Symbol 小妙处
  • 原文地址:https://www.cnblogs.com/83131yyl/p/5085615.html
Copyright © 2011-2022 走看看