前言:
几个月前去的这场,只打了240分,t3做乱了,转到t4看完题目直接就开始写pushup和pushdown了,把线段树板子敲完才发现线段树没法做。。。最后连暴力都没写出来。老早就看了t4的官方题解,今天才想起来补,然后这题操作1属实有点难写,又因为两个bug调了两个小时。过两天就去下一场了,希望能>300分。
思路:
我是看官方题解做出来的,所以思路和题解一样。
操作1:总体是要维护1~n这些人的投票情况,最大1e9的n用数组维护无论从时间还是空间来看都不可能。所以考虑把连续的投票意愿相同的人看作一个块,用结构体表示,放到set里维护。
struct seg{
int id;
int l,r;
bool operator < (const seg b)const{
return l<b.l;
}
};
例如共有100个人,6~66号的人投票给1号作品,其余人还没意愿,那么我们只要维护 {{0,1,5},{1,6,66},{0,67,100}}这么一个有3个元素的集合就行,0表示无意愿,1表示意愿作品的id为1,这个集合就是提到的set。
首先先说操作2、3:操作2、3如果要按题面意思模拟的话不出意外会超时。所以要采取的办法就是映射,假如要把3所有票数给6,就把3映射到6,这样在找到3的时候,就知道其实它是6的一部分。为了便于理解实现这一操作,我们有两个定义,一个叫编号,一个叫id(我乱起的)。编号就是那1~m,x号吉祥物的编号就是x,一个吉祥物自始至终只有一个编号;id是从属于编号的一个标识符号,一个吉祥物可以有很多个id,这些id都表示这一个吉祥物。而我们上面提到的结构题里存的是id,而不是存编号,我们可以通过id找编号,所以只对id做变换就可以。刚开始,x号吉祥物有一个编号x和一个id:x。要实现操作2,即把x的票数给y,就只需要把x的所有id给到y。要实现操作3,就只需要交换x和y全部的id。这种集合的合并直接用并查集,具体实现是用一个h数组,h[x]连接着一个并查集的祖宗节点,这个祖宗节点也通过一个pre数组连向x,这个并查集里的节点全是x的id,就是这个图的样子,操作时2合并并查集,3交换并查集就可以了。
举个例子,某一时刻6有id:3和6,9有id:9。把6和9的票数交换,就只需要交换两个的id,于是6就有id:9,9有id:3和6,而我们的set集合不需要任何变换。在以后操作1更新集合时,比如我们遍历到了id为3或6的块,我们就能找到这其实是属于编号为9的作品的块,从而对9号作品进行该有的更新。差不多就是这样。
操作4、5:用一个tot数组维护所有作品的得票数,0表示无意愿的人数。但这里的下标是作品的编号,没有任何映射,6就是6号作品的票数,100就是100。而得票最大值就再开个set来模拟一下heap维护最大值就行了。然后操作1、2、3都需要更新tot的值,再用tot的值更新heap里的值。
每次操作1呢,就对set用upperbound求出来和[l,r]相交的两段,这两段之间的所有块都要处理,都要把这些块的id对应的编号找出来,然后更新tot的值,和[l,r]相交的两端要分割(删除再插入),中间的直接删了,挺难写的,细心点处理就行了。
#include<bits/stdc++.h>
using namespace std;
struct seg{
int id;
int l,r;
bool operator < (const seg b)const{
return l<b.l;
}
};
struct Node{
int id,cnt;
bool operator > (const Node b)const{
if(cnt==b.cnt) return id<b.id;
return cnt>b.cnt;
}
};
int n,m,q,idx,op;
int tot[100010];
int p[200010],h[200010],pre[200010];
set<seg> se;
set<Node,greater<Node> > heap;
void init(){//初始化
tot[0]=n;
se.insert({0,1,n});
for(int i=0;i<=m;i++){
p[i]=h[i]=pre[i]=i;
heap.insert({i,tot[i]});
}
idx=m+1;
}
int find(int x){
if(x!=p[x]) p[x]=find(p[x]);
return p[x];
}
int mid(int x){//通过编号找到任一个id
return h[x];
}
int idm(int x){//通过id找到唯一的编号
return pre[find(x)];
}
void modify(int x,int l,int r){//操作1
auto ita=se.upper_bound({0,l,0});
auto itb=se.upper_bound({0,r,0});
ita--;
// cout<<(*ita).l<<(*ita).r<<endl;
vector<seg> win;//待新插入的节点
vector<set<seg>::iterator> wer;//待删除的节点
win.push_back({mid(x),l,r});
auto temp=heap.find({x,tot[x]});
heap.erase(temp);
tot[x]+=(r-l+1);
heap.insert({x,tot[x]});
for(auto it=ita;it!=itb;it++) wer.push_back(it);
for(int i=0;i<wer.size();i++){
seg t=*wer[i];
se.erase(t);
if(l>=t.l&&r<=t.r){//[t.l [l r] t.r]的情况
if(l-1>=t.l) win.push_back({t.id,t.l,l-1});
if(r+1<=t.r) win.push_back({t.id,r+1,t.r});
Node tc=*heap.find({idm(t.id),tot[idm(t.id)]});
heap.erase(tc);
tot[tc.id]-=(r-l+1);
heap.insert({tc.id,tot[tc.id]});
}
else if(l<=t.r&&t.l<=l){//[t.l [l t.r] r]的情况
if(l-1>=t.l) win.push_back({t.id,t.l,l-1});
Node tc=*heap.find({idm(t.id),tot[idm(t.id)]});
heap.erase(tc);
tot[tc.id]-=(t.r-l+1);
heap.insert({tc.id,tot[tc.id]});
}
else if(r<=t.r&&t.l<=r){//[l [t.l r] t.r]的情况
if(r+1<=t.r) win.push_back({t.id,r+1,t.r});
Node tc=*heap.find({idm(t.id),tot[idm(t.id)]});
heap.erase(tc);
tot[tc.id]-=(r-t.l+1);
heap.insert({tc.id,tot[tc.id]});
}
else if(l<t.l&&r>t.r){//[l [t.l t.r] r]的情况
Node tc=*heap.find({idm(t.id),tot[idm(t.id)]});
heap.erase(tc);
tot[tc.id]-=(t.r-t.l+1);
heap.insert({tc.id,tot[tc.id]});
}
}
for(int i=0;i<win.size();i++) se.insert(win[i]);
}
void exchange(int x,int y){//操作3
heap.erase({x,tot[x]}),heap.erase({y,tot[y]});
int a=h[x],b=h[y];
pre[a]=y,pre[b]=x;
swap(h[x],h[y]);
swap(tot[x],tot[y]);
heap.insert({x,tot[x]});
heap.insert({y,tot[y]});
}
void xtoy(int x,int y){//操作2
heap.erase({x,tot[x]}),heap.erase({y,tot[y]});
p[h[x]]=h[y];
p[idx]=idx;
h[x]=idx;
pre[idx++]=x;
tot[y]+=tot[x];
tot[x]=0;
heap.insert({x,tot[x]});
heap.insert({y,tot[y]});
}
void debug(){//没用不用管
cout<<"--------------------------------------"<<endl;
for(auto it=se.begin();it!=se.end();it++){
seg t=*it;
cout<<t.l<<" "<<t.r<<" "<<idm(t.id)<<" "<<tot[idm(t.id)]<<endl;
}
cout<<"--------------------------------------"<<endl;
// cout<<"--------------------------------------"<<endl;
// for(auto it=heap.begin();it!=heap.end();it++){
// Node t=*it;
// cout<<t.cnt<<" "<<tot[t.id]<<" "<<t.id<<endl;
// }
// cout<<"--------------------------------------"<<endl;
}
int main(){
cin>>n>>m>>q;
init();
while(q--){
// debug();
cin>>op;
if(op==1){
int l,r,x;
cin>>l>>r>>x;
modify(x,l,r);
}
else if(op==2){
int x,y;
cin>>x>>y;
xtoy(x,y);
}
else if(op==3){
int x,y;
cin>>x>>y;
exchange(x,y);
}
else if(op==4){
int x;
cin>>x;
cout<<tot[x]<<endl;
}
// else if(op==9){
// int x;
// cin>>x;
// cout<<"--->"<<idm(x)<<endl;
// }
else{
if(tot[0]==n) cout<<0<<endl;
else{
if((*heap.begin()).id) cout<<(*heap.begin()).id<<endl;
else cout<<(*(++heap.begin())).id<<endl;
}
}
}
system("pause");
}