一道及其恶心的题
大概题意就是维护动态的区间中大于一半的数
怎么办呢?我们把这个过程拆成两部分
- 维护区间众数
- 判断众数是不是大于一半
对于第一步,我们可以用线段树来维护
对于第二步,我们可以用平衡树来维护
所以,这道题就是线段树+平衡树
首先线段树维护两个量 v a l val val和 c n t cnt cnt分别表示当前区间的众数和这个区间的众数的优势(比第二大的多多少)
那么
p
u
s
h
u
p
pushup
pushup也不难,就是
d
e
f
i
n
e
:
l
c
=
u
<
<
1
,
r
c
=
u
<
<
1
∣
1
define :lc=u<<1,rc=u<<1|1
define:lc=u<<1,rc=u<<1∣1
v
a
l
[
u
]
=
v
a
l
[
l
c
]
,
c
n
t
[
u
]
=
c
n
t
[
l
c
]
+
c
n
t
[
r
c
]
(
v
a
l
[
l
c
]
=
v
a
l
[
r
c
]
)
val[u]=val[lc],cnt[u]=cnt[lc]+cnt[rc](val[lc]=val[rc])
val[u]=val[lc],cnt[u]=cnt[lc]+cnt[rc](val[lc]=val[rc])
e
l
s
e
:
v
a
l
[
u
]
=
(
c
n
t
[
l
c
]
>
c
n
t
[
r
c
]
?
v
a
l
[
l
c
]
:
v
a
l
[
r
c
]
)
,
c
n
t
[
u
]
=
a
b
s
(
c
n
t
[
l
c
]
−
c
n
t
[
r
c
]
)
else:val[u]=(cnt[lc]>cnt[rc]?val[lc]:val[rc]),cnt[u]=abs(cnt[lc]-cnt[rc])
else:val[u]=(cnt[lc]>cnt[rc]?val[lc]:val[rc]),cnt[u]=abs(cnt[lc]−cnt[rc])
统计的时候就瞎区间查询就可以
接下来我们给每个人写一个平衡树,表示支持他的人的
i
d
id
id
我们把可能是答案的值从线段树里查询出来之后就往这个人的平衡树里查询,看是不是大于区间的一半
这题恶心在要写两颗树,而且都不太好写(特别是这题的线段树我调了两天)
# include <cstdio>
# include <algorithm>
# include <cstring>
# include <cmath>
# include <climits>
# include <iostream>
# include <string>
# include <queue>
# include <stack>
# include <vector>
# include <set>
# include <map>
# include <cstdlib>
# include <ctime>
using namespace std;
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)
typedef long long ll;
const int N=5e5+5;
const int inf=0x7fffffff;
const double eps=1e-7;
template <typename T> void read(T &x){
x=0;int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
x*=f;
}
int n,m,tot;
int stand[N];
struct segment_tree_node{
int l,r,val,cnt;
}seg[N<<2];
int fa[N*10],son[N*10][2],siz[N*10],key[N*10];
struct segment_tree{
# define lc (u<<1)
# define rc (u<<1|1)
void pushup(int u){
if(seg[lc].val==seg[rc].val)seg[u].val=seg[lc].val,seg[u].cnt=seg[lc].cnt+seg[rc].cnt;
else if(seg[lc].cnt>=seg[rc].cnt)seg[u].cnt=seg[lc].cnt-seg[rc].cnt,seg[u].val=seg[lc].val;
else seg[u].cnt=seg[rc].cnt-seg[lc].cnt,seg[u].val=seg[rc].val;
}
void build(int u,int l,int r){
seg[u].l=l,seg[u].r=r;
if(l==r){seg[u].val=stand[l],seg[u].cnt=1;return;}
int mid=l+r>>1;
build(lc,l,mid);
build(rc,mid+1,r);
pushup(u);
}
void update(int u,int x,int k){
if(seg[u].l==seg[u].r){seg[u].val=k;seg[u].cnt=1;return;}
int mid=seg[u].l+seg[u].r>>1;
if(x<=mid)update(lc,x,k);
else update(rc,x,k);
pushup(u);
}
segment_tree_node query(int u,int l,int r){
if(seg[u].l==l&&seg[u].r==r)return seg[u];
int mid=seg[u].l+seg[u].r>>1;
if(r<=mid)return query(lc,l,r);
if(l>mid)return query(rc,l,r);
segment_tree_node a=query(lc,l,mid),b=query(rc,mid+1,r),c;
if(a.val==b.val)c.val=a.val,c.cnt=a.cnt+b.cnt;
else if(a.cnt>=b.cnt)c.val=a.val,c.cnt=a.cnt-b.cnt;
else c.val=b.val,c.cnt=b.cnt-a.cnt;
return c;
}
}a;
struct Splay{
int rt;
void clear(int x){fa[x]=son[x][0]=son[x][1]=siz[x]=key[x]=0;}
bool locate(int x){return son[fa[x]][1]==x;}
void update(int x){siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;}
int create(int x,int faz){
tot++;
fa[tot]=faz,key[tot]=x;
son[tot][0]=son[tot][1]=0;
siz[tot]=1;
return tot;
}
void rotate(int x){
int faz=fa[x],grand=fa[faz],side=locate(x);
son[faz][side]=son[x][side^1],fa[son[faz][side]]=faz;
son[x][side^1]=faz,fa[faz]=x;
fa[x]=grand;
if(grand)son[grand][son[grand][1]==faz]=x;
update(faz),update(x);
}
void splay(int x,int tar){
if(!tar)rt=x;
while(fa[x]!=tar){
if(fa[fa[x]]!=tar)rotate(locate(x)==locate(fa[x])?fa[x]:x);
rotate(x);
}
}
void find(int x){
int u=rt;if(!u)return;
while(son[u][x>key[u]]&&key[u]!=x)u=son[u][x>key[u]];
splay(u,0);
}
int pre(int x){
int u=rt;
if(key[u]<x)return u;
u=son[rt][0];
while(son[u][1])u=son[u][1];
return u;
}
int rank(int x){
find(x);
if(key[rt]!=x)x=key[pre(x)];
int u=rt,res=0;
while(1){
if(x<key[u])u=son[u][0];
else{
res+=siz[son[u][0]];
if(x==key[u]){
splay(u,0);
return res;
}
res++;
u=son[u][1];
}
}
}
void insert(int x){
if(!rt){
rt=create(x,0);
return;
}
int u=rt,faz=0;
while(1){
faz=u,u=son[u][x>key[u]];
if(!u){
son[faz][x>key[faz]]=create(x,faz);
update(faz);
splay(tot,0);
return;
}
}
}
void erase(int x){
find(x);
if(!son[rt][0]&&!son[rt][1]){
clear(rt);
rt=0;
return;
}
if(!son[rt][0]){
int old=rt;
rt=son[rt][1];
fa[rt]=0;
clear(old);
return;
}
if(!son[rt][1]){
int old=rt;
rt=son[rt][0];
fa[rt]=0;
clear(old);
return;
}
int old=rt,lft=pre(key[rt]);
splay(lft,0);
son[rt][1]=son[old][1];
fa[son[old][1]]=rt;
clear(old);
update(rt);
}
}b[N];
int main()
{
//freopen("p3765.in","r",stdin);
read(n),read(m);
Rep(i,1,n)read(stand[i]),b[stand[i]].insert(i);
Rep(i,1,n)b[i].insert(-1e9),b[i].insert(1e9);
a.build(1,1,n);
Rep(i,1,m){
int l,r,s,q;
read(l),read(r),read(s),read(q);
int x=a.query(1,l,r).val;
int sum=b[x].rank(r)-b[x].rank(l-1);
if(sum>(r-l+1)/2)s=x;
while(q--){
read(x);
a.update(1,x,s);
b[stand[x]].erase(x);
stand[x]=s;
b[stand[x]].insert(x);
}
printf("%d\n",s);
}
int x=a.query(1,1,n).val;
int sum=b[x].rank(n);
printf("%d\n",sum>(n/2)?x:-1);
return 0;
}