zoukankan      html  css  js  c++  java
  • BZOJ3524 [POI2014] Couriers

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3524

    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行,每行对应一个答案。

    主席树 OrzTLE Orz林教主 建的是权值线段树。

    最开始一直不懂为什么可以在权值线段树上二分一个数来判断它是否符合条件,后来明白了

    如果存在一个数出现次数大于(r-l+1)/2,它的出现次数不仅是最大,而且比其他的数加起来的都要大

    那么它所在的左边那一半或右边那一半的出现次数总和肯定大于另一半的总和

    所以二分后如果存在就一定能找到那个数

    注意数组大小,这题卡空间……

    做了一下询问过程加inline,不加inline和直接塞进主函数的效率对比

    从上到下依次是直接塞进主函数,加inline,不加inline

    加与不加之间相差大约300ms,直接塞进主函数和加inline运行时间没有太大区别

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #define rep(i,l,r) for(int i=l; i<=r; i++)
     6 #define clr(x,y) memset(x,y,sizeof(x))
     7 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
     8 using namespace std;
     9 const int INF = 0x3f3f3f3f;
    10 const int maxn = 500010;
    11 int n,m,x,y,tot=0,a[maxn],root[maxn],ls[maxn*20],rs[maxn*20],sum[maxn*20];
    12 inline int read(){
    13     int ans = 0, f = 1;
    14     char c = getchar();
    15     while (!isdigit(c)){
    16         if (c == '-') f = -1;
    17         c = getchar();
    18     }
    19     while (isdigit(c)){
    20         ans = ans * 10 + c - '0';
    21         c = getchar();
    22     }
    23     return ans * f;
    24 }
    25 void insert(int l,int r,int x,int &y,int v){
    26     y = ++tot;
    27     sum[y] = sum[x] + 1;
    28     if (l == r) return;
    29     ls[y] = ls[x]; rs[y] = rs[x];
    30     int mid = (l + r) >> 1;
    31     if (v <= mid) insert(l,mid,ls[x],ls[y],v);
    32     else insert(mid+1,r,rs[x],rs[y],v);
    33 }
    34 inline void query(int x,int y){
    35     int l=1,r=n,a=root[y],b=root[x-1];
    36     while (l < r){
    37         int mid = (l + r) >> 1;
    38         if (sum[ls[a]] - sum[ls[b]] > sum[rs[a]] - sum[rs[b]]){
    39             a = ls[a]; b = ls[b]; r = mid;
    40         }
    41         else{
    42             a = rs[a]; b = rs[b]; l = mid + 1;
    43         }
    44     }
    45     if (sum[a] - sum[b] > (y - x + 1) >> 1) printf("%d
    ",l);
    46     else printf("0
    ");
    47 }
    48 int main(){
    49     n = read(); m = read();
    50     rep(i,1,n) a[i] = read();
    51     rep(i,1,n) insert(1,n,root[i-1],root[i],a[i]);
    52     rep(i,1,m){
    53         x = read(); y = read();
    54         query(x,y);
    55     }
    56     return 0;
    57 }
    View Code
  • 相关阅读:
    spring boot 中使用redis session
    关于 JVM 内存的 N 个问题(转)
    在JAVA中记录日志的十个小建议
    spring boot jpa 多数据源配置
    python高性能web框架——Japronto
    毕业 3 年,为何技术能力相差越来越大?——转自阿里技术人生
    如何成为技术大牛——阿里CodeLife
    布式之数据库和缓存双写一致性方案解析(转)
    海量数据存储--分库分表策略详解 (转)
    Linux内核模块简单示例
  • 原文地址:https://www.cnblogs.com/jimzeng/p/bzoj3524.html
Copyright © 2011-2022 走看看