NOI2022 众数
经典题目,对于绝对众数只需要考虑这一个序列的中位数在序列中出现次数是否大于一半即可。
这道题用线段树合并维护一下就做完了。
点击查看代码
#include<bits/stdc++.h> #define fir first #define sec second #define int long long #define mkp(a,b) make_pair(a,b) using namespace std; typedef pair<int,int> pir; inline int read(){ int x=0,f=1; char c=getchar(); while(!isdigit(c)){if(c=='-') f=-1; c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48); c=getchar();} return x*f; } const int mod=998244353,inf=1e18,N=1e6+5; int n,q,lim; int siz[N]; int nxt[N],pre[N],val[N],rt[N],lst[N],fst[N],cnt; int m; int qu[N],p[N]; struct tree{ int cnt; int sum[N*20],ls[N*20],rs[N*20]; inline void push_up(int p){sum[p]=sum[ls[p]]+sum[rs[p]];} inline void add(int &p,int l,int r,int num,int k){ if(!p) p=++cnt; if(l==r){sum[p]+=k; return ;} int mid=(l+r)>>1; if(num<=mid) add(ls[p],l,mid,num,k); if(num>mid) add(rs[p],mid+1,r,num,k); push_up(p); } inline int merge(int p,int q,int l,int r){ if(!p||!q) return p^q; if(l==r){sum[p]+=sum[q]; return p;} int mid=(l+r)>>1; ls[p]=merge(ls[p],ls[q],l,mid); rs[p]=merge(rs[p],rs[q],mid+1,r); push_up(p); return p; } inline int ask(int p,int l,int r,int num){ if(l==r) return sum[p]; int mid=(l+r)>>1; if(num<=mid) return ask(ls[p],l,mid,num); return ask(rs[p],mid+1,r,num); } inline int find(int p[],int l,int r,int S){ if(l==r) return l; int mid=(l+r)>>1; int le=0; for(int i=1;i<=m;i++) le+=sum[ls[p[i]]]; if(S>le){ for(int i=1;i<=m;i++) p[i]=rs[p[i]]; return find(p,mid+1,r,S-le); } for(int i=1;i<=m;i++) p[i]=ls[p[i]]; return find(p,l,mid,S); } }T; inline void add(int x,int y){ cnt++; siz[x]++; val[cnt]=y; int ed=lst[x]; if(ed){ nxt[ed]=cnt; pre[cnt]=ed; } lst[x]=cnt; if(siz[x]==1) fst[x]=cnt; T.add(rt[x],1,lim,y,1); } inline void del(int x){ siz[x]--; if(!siz[x]) fst[x]=0; int ed=lst[x],y=val[ed]; // cout<<"del:"<<x<<' '<<ed<<' '<<y<<'\n'; lst[x]=pre[ed]; nxt[pre[ed]]=0; nxt[ed]=pre[ed]=0; T.add(rt[x],1,lim,y,-1); } inline void ask(){ m=read(); int sum=0; for(int i=1;i<=m;i++){ int x=read(); qu[i]=p[i]=rt[x],sum+=siz[x]; } int it=T.find(p,1,lim,sum/2+1),C=0; for(int i=1;i<=m;i++) C+=T.ask(qu[i],1,lim,it); // cout<<it<<' '<<C<<' '<<sum/2<<'\n'; if(C<=sum/2) puts("-1"); else cout<<it<<'\n'; } inline void merge(int x,int y,int z){ rt[z]=T.merge(rt[x],rt[y],1,lim); siz[z]=siz[x]+siz[y]; int ed=lst[x],fi=fst[y]; nxt[ed]=fi,pre[fi]=ed; if(!ed) nxt[ed]=0; if(!fi) pre[fi]=0; fst[z]=(siz[x]?fst[x]:fst[y]),lst[z]=(siz[y]?lst[y]:lst[x]); fst[x]=fst[y]=lst[x]=lst[y]=0; } signed main(){ // freopen("major.in","r",stdin); // freopen("major.out","w",stdout); n=read(),q=read(); lim=n+q; for(int i=1;i<=n;i++){ siz[i]=read(); for(int j=1;j<=siz[i];j++){ int x=read(); val[++cnt]=x; T.add(rt[i],1,lim,x,1); nxt[cnt]=cnt+1,pre[cnt]=cnt-1; if(j==1) pre[cnt]=0,fst[i]=cnt; if(j==siz[i]) nxt[cnt]=0,lst[i]=cnt; } // cout<<cnt<<'\n'; } while(q--){ int opt=read(); if(opt==1){ int x=read(),y=read(); add(x,y); } if(opt==2){ int x=read(); del(x); } if(opt==3) ask(); if(opt==4){ int x=read(),y=read(),z=read(); merge(x,y,z); } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类