1. 程式人生 > >【BZOJ3524】Couriers

【BZOJ3524】Couriers

二分 str 維護 memset 表示 i++ tor algo eof

題面

Description

給一個長度為\(n\)的序列\(a\)\(1\le a[i]\le 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\le 500000\)


分析

主席樹維護權值線段樹,直接在樹上二分。

#include<cstdio>  
#include<iostream>  
#include<algorithm>  
#include<cstdlib>  
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<ctime>
#define LL long long
#define inf 0x3f3f3f3f

using namespace std;

inline char nc(){
    /* 
  static char buf[100000],*p1=buf,*p2=buf;
  if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
  return *p1++;
    */return getchar();
}
  
inline void read(int &x){
  char c=nc();int b=1;
  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
  
inline void read(LL &x){
  char c=nc();LL b=1;
  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
 
inline void read(char &x){
  for (x=nc();!(x=='('||x==')');x=nc());
}

inline int read(char *s)
{
    char c=nc();int len=1;
    for(;!(c=='('||c==')');c=nc()) if (c==EOF) return 0;
    for(;(c=='('||c==')');s[len++]=c,c=nc());
    s[len++]='\0';
    return len-2;
}
int wt,ss[19];
inline void print(int x){
    if (x<0) x=-x,putchar('-'); 
    if (!x) putchar(48); else {
    for (wt=0;x;ss[++wt]=x%10,x/=10);
    for (;wt;putchar(ss[wt]+48),wt--);}
}
inline void print(LL x){
    if (x<0) x=-x,putchar('-');
    if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
}

int T,n,m,s,k,h[500010],b[500010],d[500010];
struct ST
{
    int lc,rc,sum;
}a[10000010];

void build(int l,int r,int x)
{
    s++;x=s;
    if (l==r) {a[x].lc=a[x].rc=0;return ;}
    int mid=(l+r)>>1;
    a[x].lc=s+1;build(l,mid,x);
    a[x].rc=s+1;build(mid+1,r,x);
}

void change(int x,int y,int z,int xx,int l,int r)     //新結點編號,,,對應結點編號,[l,r]
{
    if (l==r) {a[x].sum=a[xx].sum+z;return ;}
    int mid=(l+r)>>1;
    if (y<=mid)
    {
        a[x].rc=a[xx].rc;
        s++;a[x].lc=s;
        change(s,y,z,a[xx].lc,l,mid);
    }
    else
    {
        a[x].lc=a[xx].lc;
        s++;a[x].rc=s;
        change(s,y,z,a[xx].rc,mid+1,r);
    }
    a[x].sum=a[a[x].lc].sum+a[a[x].rc].sum;
}

int query(int x,int y,int z,int l,int r)
{
    //printf("%d %d %d %d\n",l,r,z,a[y].sum-a[x].sum);
    if (l==r)
    {
        if (a[y].sum-a[x].sum>z) return b[l];
        else return 0;
    }
    if (a[a[y].lc].sum-a[a[x].lc].sum>z) return query(a[x].lc,a[y].lc,z,l,(l+r)>>1);
    else if (a[a[y].rc].sum-a[a[x].rc].sum>z) return query(a[x].rc,a[y].rc,z,((l+r)>>1)+1,r);
    else return 0;
}

int main()
{
    read(n);read(m);
    memset(a,0,sizeof(a));
    for (int i=1;i<=n;i++)
        read(d[i]),b[i]=i;
    s=0;
    build(1,n,1);
    h[0]=1;
    for (int i=1;i<=n;i++)
    {
        s++;h[i]=s;
        change(s,d[i],1,h[i-1],1,n); 
    }
    int x,y,z;
    while(m--)
    {
        read(x);read(y);
        print(query(h[x-1],h[y],(y-x+1)/2,1,n));putchar('\n');
    }
    return 0;
}

【BZOJ3524】Couriers