社区讨论
求助超时
P8496[NOI2022] 众数参与者 1已保存回复 1
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @lo75hkmg
- 此快照首次捕获于
- 2023/10/26 20:18 2 年前
- 此快照最后确认于
- 2023/11/02 11:18 2 年前
emmm,找不到哪里超时了,感觉算法复杂度没问题但是本机145秒......,应该是操作3或者操作4,求助各路大佬,人多力量大。
CPP#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1000005;
int head[N],tail[N],pre[N],val[N],sz[N];
int id=0;
void pushback(int x,int y){//在序列x后面添加y
id++;
if(!head[x])
head[x]=id;
val[id]=y;
pre[id]=tail[x];
tail[x]=id;
}
void pop(int x){//解决掉最后一个
sz[x]--;
tail[x]=pre[tail[x]];
if(sz[x]==0){
head[x]=0;
}
}
int roots[N];
int cnt=0;
struct node{
int ls;
int rs;
int ex;//消除后剩余的颜色
int sum;//消除后的sum
int siz; //不消除总共的sum。
}tree[10*N];
void pushupp(int rt){
tree[rt].siz=tree[tree[rt].ls].siz+tree[tree[rt].rs].siz;
if(tree[tree[rt].ls].sum>tree[tree[rt].rs].sum){
tree[rt].sum=tree[tree[rt].ls].sum-tree[tree[rt].rs].sum;
tree[rt].ex=tree[tree[rt].ls].ex;
}
else{
tree[rt].sum=tree[tree[rt].rs].sum-tree[tree[rt].ls].sum;
tree[rt].ex=tree[tree[rt].rs].ex;
}
}
int add(int rt,int le,int ri,int pos,int val){
if(pos<le||pos>ri){
return rt;
}
if(!rt){
cnt++;
rt=cnt;
}
if(le==ri){
tree[rt].sum+=val;
tree[rt].ex=pos;
tree[rt].siz+=val;
return rt;
}
int mid=(le+ri)>>1;
tree[rt].ls=add(tree[rt].ls,le,mid,pos,val);
tree[rt].rs=add(tree[rt].rs,mid+1,ri,pos,val);
pushupp(rt);//直接开始消除
return rt;
}
int merge(int newroot,int roota,int rootb,int le,int ri){//合并操作(不知道是不是对的)
if(!roota&&!rootb){
return newroot;
}
if(!newroot){
cnt++;
newroot=cnt;
}
int mid=(le+ri)/2;
if(!roota){
tree[newroot]=tree[rootb];
tree[newroot].ls=merge(tree[newroot].ls,tree[roota].ls,tree[rootb].ls,le,mid);
tree[newroot].rs=merge(tree[newroot].rs,tree[roota].rs,tree[rootb].rs,mid+1,ri);
return newroot;
}
if(!rootb){
tree[newroot]=tree[roota];
tree[newroot].ls=merge(tree[newroot].ls,tree[roota].ls,tree[rootb].ls,le,mid);
tree[newroot].rs=merge(tree[newroot].rs,tree[roota].rs,tree[rootb].rs,mid+1,ri);
return newroot;
}
if(le==ri){
tree[newroot].ex=tree[roota].ex;
tree[newroot].sum=tree[roota].sum+tree[rootb].sum;
tree[newroot].siz=tree[roota].siz+tree[rootb].siz;
return newroot;
}
tree[newroot].ls=merge(tree[newroot].ls,tree[roota].ls,tree[rootb].ls,le,mid);
tree[newroot].rs=merge(tree[newroot].rs,tree[roota].rs,tree[rootb].rs,mid+1,ri);
pushupp(newroot);
return newroot;
}
int query(int rt,int pos,int le,int ri){
if(pos<le||pos>ri){
return 0;
}
if(le==ri){
return tree[rt].sum;
}
int ret=0;
int mid=(le+ri)>>1;
ret+=query(tree[rt].ls,pos,le,mid);
ret+=query(tree[rt].rs,pos,mid+1,ri);
return ret;
}
vector<int>vec;
signed main(){
// freopen("major11.in","r",stdin);
// freopen("ans.out","w",stdout);
int n,q;
scanf("%lld%lld",&n,&q);
int maxn=n+q;
int fc=n;
for(int i=1;i<=n;i++){
int m;
scanf("%lld",&m);
cnt++;
roots[i]=cnt;
for(int j=1;j<=m;j++){
int u;
scanf("%lld",&u);
pushback(i,u);
add(roots[i],0,maxn,u,1);
sz[i]++;
// printf("test:%lld\n",tree[roots[i]].ex);
}
}
while(q--){
int op;
scanf("%lld",&op);
if(op==1){
int x,y;
scanf("%lld%lld",&x,&y);
pushback(x,y);
add(roots[x],0,maxn,y,1);
}
else if(op==2){
int x;
scanf("%lld",&x);
add(roots[x],0,maxn,val[tail[x]],-1);
pop(x);
}
else if(op==3){
int m;
scanf("%lld",&m);
vec.clear();
int col=-1;
int colsum=0;
for(int i=1;i<=m;i++){
int u;
scanf("%lld",&u);
vec.push_back(u);
int rt=roots[u];
if(tree[rt].ex==col){
colsum+=tree[rt].sum;
}
else{
if(tree[rt].sum>=colsum){
colsum=tree[rt].sum-colsum;
col=tree[rt].ex;
}
else{
colsum=colsum-tree[rt].sum;
}
}
}
int sum=0;
int sumsz=0;
for(int i=0;i<vec.size();i++){
int rt=roots[vec[i]];
sum+=query(rt,col,0,maxn);
sumsz+=tree[rt].siz;
}
int seil=floor(1.0*sumsz/2);
if(sum>seil){
printf("%lld\n",col);
}
else{
printf("-1\n");
}
}
else if(op==4){
int a,b,c;
scanf("%lld%lld%lld",&a,&b,&c);
roots[c]=merge(roots[c],roots[a],roots[b],1,maxn);
if(tail[b])
tail[c]=tail[b];
else
tail[c]=tail[a];
if(head[a])
head[c]=head[a];
else
head[c]=head[b];
if(head[b])
pre[head[b]]=tail[a];
sz[c]=sz[a]+sz[b];
sz[a]=sz[b]=head[a]=head[b]=tail[a]=tail[b]=0;
}
}
}
回复
共 1 条回复,欢迎继续交流。
正在加载回复...