[NOI2022] 众数 题解
看到绝对众数的出现,摩尔投票法直接秒了,考虑分为若干个序列,要支持合并操作,那么容易想到线段树,要删除尾部,容易想到链表,因为\(\sum M \le 10^5\),所以在查询的时候可以暴力枚举序列,进行摩尔投票,然后判断剩余的数是不是绝对众数,复杂度\(O(n\log_2{n})\)。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e6+10;
int n,m,rt[maxn],op,x,y,z,ans,idd,ge[maxn],jie,nxt[maxn],pre[maxn],fir,sec;
int t[maxn],qi[maxn],news,luo[maxn],val[maxn],lst,rts,now,tp,st[maxn];
struct edge{
int ls;
int rs;
int fir;
int sec;
int sum;
}tree[maxn<<4];
inline void push_up(int id){
if(tree[tree[id].ls].sec>tree[tree[id].rs].sec){
tree[id].fir=tree[tree[id].ls].fir;
tree[id].sec=tree[tree[id].ls].sec-tree[tree[id].rs].sec;
}
else if(tree[tree[id].ls].sec==tree[tree[id].rs].sec){
tree[id].fir=tree[id].sec=0;
}
else{
tree[id].fir=tree[tree[id].rs].fir;
tree[id].sec=tree[tree[id].rs].sec-tree[tree[id].ls].sec;
}
return;
}
inline void add(int &id,int l,int r,int q,int w){
if(!id){
idd++;
id=idd;
}
if(l==r){
tree[id].sum+=w;
tree[id].fir=l;
tree[id].sec=tree[id].sum;
return;
}
int mid=(l+r)/2;
if(q<=mid){
add(tree[id].ls,l,mid,q,w);
}
else{
add(tree[id].rs,mid+1,r,q,w);
}
push_up(id);
return;
}
inline int merges(int q,int w){
if(!q||!w){
return q+w;
}
if(!tree[q].ls&&!tree[q].rs){
tree[q].sum+=tree[w].sum;
tree[q].sec+=tree[w].sec;
return q;
}
tree[q].ls=merges(tree[q].ls,tree[w].ls);
tree[q].rs=merges(tree[q].rs,tree[w].rs);
push_up(q);
return q;
}
inline int query(int id,int l,int r,int q){
if(l==r){
return tree[id].sum;
}
int mid=(l+r)/2;
if(q<=mid){
return query(tree[id].ls,l,mid,q);
}
else{
return query(tree[id].rs,mid+1,r,q);
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
jie=n+m;
for(int i=1;i<=n;i++){
cin>>ge[i];
for(int j=1;j<=ge[i];j++){
cin>>x;
news++;
val[news]=x;
if(!qi[i]){
qi[i]=news;
}
else{
pre[news]=lst;
nxt[lst]=news;
}
lst=news;
luo[i]=news;
add(rt[i],1,jie,x,1);
}
}
while(m--){
cin>>op;
if(op==1){
cin>>x>>y;
news++;
val[news]=y;
if(!qi[x]){
qi[x]=news;
}
else{
pre[news]=luo[x];
nxt[luo[x]]=news;
}
luo[x]=news;
add(rt[x],1,jie,y,1);
ge[x]++;
}
if(op==2){
cin>>x;
add(rt[x],1,jie,val[luo[x]],-1);
luo[x]=pre[luo[x]];
ge[x]--;
if(!luo[x]){
qi[x]=0;
}
}
if(op==3){
cin>>x;
tp=0;
for(int i=1;i<=x;i++){
tp++;
cin>>st[tp];
}
y=0,z=0,now=idd,rts=0,fir=0,sec=0;
for(int i=1;i<=x;i++){
y+=ge[st[i]];
}
for(int i=1;i<=x;i++){
if(tree[rt[st[i]]].fir==fir){
sec+=tree[rt[st[i]]].sec;
}
else if(tree[rt[st[i]]].sec==sec){
fir=0;
sec=0;
}
else if(tree[rt[st[i]]].sec>sec){
fir=tree[rt[st[i]]].fir;
sec=tree[rt[st[i]]].sec-sec;
}
else{
sec-=tree[rt[st[i]]].sec;
}
}
for(int i=1;i<=x;i++){
z+=query(rt[st[i]],1,jie,fir);
}
if(z>y/2){
cout<<fir<<'\n';
}
else{
cout<<-1<<'\n';
}
}
if(op==4){
cin>>x>>y>>z;
rt[z]=merges(rt[x],rt[y]);
ge[z]=ge[x]+ge[y];
if(ge[x]&&ge[y]){
qi[z]=qi[x];
nxt[luo[x]]=qi[y];
pre[qi[y]]=luo[x];
luo[z]=luo[y];
}
else if(ge[x]){
qi[z]=qi[x];
luo[z]=luo[x];
}
else{
qi[z]=qi[y];
luo[z]=luo[y];
}
}
}
return 0;
}
浙公网安备 33010602011771号