题目描述
数据结构
对每个小组用两个数据结构维护,分别维护体力和刷题量。
对于合并的操作,可以启发式合并。
单个修改直接在对应的数据结构里改。
小组修改可以通过打tag实现,这个tag只有在这个小组被并进另一个小组的时候才下传。注意这个tag是永久化的,因此并进另一个小组时,要把它们对另一个小组的tag进行反作用。
淘汰人可以在对应数据结构进行修改。
为了方便做考核操作,每个小组维护出刷题量最小值,再用一个大数据结构维护出所有中的最小值。
那么这就有一些细节了,每次对小组进行更改时也要顺便来维护这个大数据结构。
每次先找到最小值,然后不断淘汰人,每次在大数据结构中的第一个小组中淘汰最小的人,一直做到大数据结构查出最小的不等于最小值。
对于编号存在情况还需要使用一个数据结构。
对于查询的话,每个小组都要保存个数和和,在各种操作中都要注意维护。
这个数据结构使用set会轻松许多,但是不会跑的很快。
这就很丧病了QAQ
#include<cstdio>
#include<algorithm>
#include<set>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=300000+10;
struct dong{
int x;
ll y;
friend bool operator <(dong a,dong b){
return a.y<b.y||a.y==b.y&&a.x<b.x;
}
} zlt;
multiset<int> id;
multiset<int>::iterator it;
multiset<dong> s,c[maxn],d[maxn];
int fa[maxn],size[maxn],belong[maxn];
ll a[maxn],b[maxn],sb[maxn],ad[maxn],mi[maxn],sum[maxn],wdc;
int sta[80];
int i,j,k,l,r,t,n,m,tot,top,cnt,num,ans,mx;
char ch;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
char get(){
char ch=getchar();
while (ch!='J'&&ch!='P'&&ch!='D'&&ch!='E'&&ch!='M'&&ch!='C'&&ch!='T'&&ch!='Q') ch=getchar();
return ch;
}
int getfa(int x){
return fa[x]?fa[x]=getfa(fa[x]):x;
}
void work(int x){
zlt.x=x;zlt.y=mi[x];
if (s.find(zlt)==s.end()) return;
s.erase(s.find(zlt));
if (d[x].begin()==d[x].end()) return;
mi[x]=(*(d[x].begin())).y+ad[x];
zlt.x=x;zlt.y=mi[x];
s.insert(zlt);
}
void del(int x){
id.erase(id.find(x));
int y=getfa(x);
zlt.x=x;zlt.y=a[x];
c[y].erase(c[y].find(zlt));
zlt.x=x;zlt.y=b[x];
d[y].erase(d[y].find(zlt));
work(y);
size[y]--;
sum[y]-=b[x];
sum[y]-=ad[y];
num--;
}
void merge(int x,int y){
x=getfa(x),y=getfa(y);
if (x==y) return;
if (size[x]>size[y]) swap(x,y);
while (!c[x].empty()){
zlt=*(c[x].begin());
zlt.y-=sb[x];
zlt.y+=sb[y];
a[zlt.x]=zlt.y;
c[y].insert(zlt);
c[x].erase(c[x].begin());
}
while (!d[x].empty()){
zlt=*(d[x].begin());
zlt.y+=ad[x];
zlt.y-=ad[y];
b[zlt.x]=zlt.y;
d[y].insert(zlt);
d[x].erase(d[x].begin());
}
zlt.x=x;zlt.y=mi[x];
s.erase(s.find(zlt));
work(y);
size[y]+=size[x];
sum[y]+=sum[x];
fa[x]=y;
}
void write(ll x){
if (!x){
putchar('0');
return;
}
top=0;
while (x){
sta[++top]=x%10;
x/=10;
}
while (top) putchar('0'+sta[top--]);
}
int main(){
freopen("training.in","r",stdin);freopen("training.out","w",stdout);
m=read();
while (m--){
ch=get();
if (ch=='J'){
++tot;
++num;
a[tot]=read();b[tot]=read();
id.insert(tot);
mi[tot]=b[tot];
zlt.x=tot;zlt.y=mi[tot];
s.insert(zlt);
d[tot].insert(zlt);
zlt.x=tot;zlt.y=a[tot];
c[tot].insert(zlt);
size[tot]=1;
sum[tot]=b[tot];
}
else if (ch=='P'){
j=read();k=read();l=read();
if (id.find(j)==id.end()) continue;
r=getfa(j);
if (a[j]-sb[r]<=k){
del(j);
continue;
}
zlt.x=j;zlt.y=a[j];
c[r].erase(c[r].find(zlt));
a[j]-=(ll)k;
zlt.x=j;zlt.y=a[j];
c[r].insert(zlt);
zlt.x=j;zlt.y=b[j];
d[r].erase(d[r].find(zlt));
b[j]+=(ll)l;
zlt.x=j;zlt.y=b[j];
d[r].insert(zlt);
sum[r]+=(ll)l;
work(r);
}
else if (ch=='D'){
j=read();k=read();l=read();
if (id.find(j)==id.end()) continue;
r=getfa(j);
sb[r]+=(ll)k;ad[r]+=(ll)l;
sum[r]+=(ll)l*size[r];
while (1){
if (c[r].begin()==c[r].end()) break;
t=(*(c[r].begin())).x;
if (a[t]-sb[r]<=0) del(t);else break;
}
work(r);
}
else if (ch=='E'){
j=read();
if (id.find(j)==id.end()) continue;
del(j);
}
else if (ch=='M'){
j=read();k=read();
if (id.find(j)==id.end()) continue;
if (id.find(k)==id.end()) continue;
merge(j,k);
}
else if (ch=='C'){
if (!num) continue;
j=*id.begin();
it=id.end();
--it;
k=*it;
merge(j,k);
}
else if (ch=='T'){
if (!num) continue;
wdc=(*s.begin()).y;
while (1){
if (s.begin()==s.end()) break;
t=(*s.begin()).y;
if (t!=wdc) break;
t=(*s.begin()).x;
t=(*d[t].begin()).x;
del(t);
}
}
else{
j=read();
if (id.find(j)==id.end()) continue;
j=getfa(j);
write(size[j]);putchar(' ');
write(sum[j]);putchar('\n');
//printf("%d %lld\n",size[j],sum[j]);
}
}
}