Files
OI-source/2.1479.cpp
2023-08-03 09:22:52 +08:00

184 lines
3.1 KiB
C++

#include<cstdlib>
struct Node
{
Node *ch[2];
int r,v,s;
Node(int v):v(v) { ch[0]=ch[1]=NULL; r=rand(); s=1; }
inline bool operator<(const Node &b) const
{
return r<b.r;
}
inline int cmp(int x) const { return x==v?-1:x>=v; }
inline void maintain()
{
s=1+(ch[0]!=NULL?ch[0]->s:0)+(ch[1]!=NULL?ch[1]->s:0);
}
};
void rotate(Node* &o,int d)
{
Node* k=o->ch[d^1];
o->ch[d^1]=k->ch[d];
k->ch[d]=o;
o->maintain();k->maintain();
o=k;
}
void insert(Node* &o,int x)
{
if(o==NULL) o=new Node(x);
else
{
int d=(x < o->v ? 0 : 1);
insert(o->ch[d],x);
if(o->ch[d]->r > o->r) rotate(o,d^1);
}
o->maintain();
}
void remove(Node* &o,int x)
{
int d=o->cmp(x);
if(d==-1)
{
Node* u=o;
if(o->ch[0]!=NULL&&o->ch[1]!=NULL)
{
int d2= (o->ch[0]->r > o->ch[1]->r ? 1: 0);
rotate(o,d2);
remove(o->ch[d2],x);
}
else
{
if(o->ch[0]==NULL) o=o->ch[1];
else o=o->ch[0];
delete u;
}
}
else remove(o->ch[d],x);
if(o!=NULL) o->maintain();
}
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxcmd=500010;
struct Command
{
char type;
int x,p;
} cmds[maxcmd];
const int maxn=20010;
const int maxm=60010;
int n,m,w[maxn],f[maxm],t[maxm],rmvd[maxm];
int fa[maxn];
int ff(int x) { return fa[x]!=x?fa[x]=ff(fa[x]):x; }
Node* root[maxn];
int kth(Node *o,int k)
{
if(o==NULL||k<=0||k > o->s) return 0;
int s=(o->ch[1]==NULL?0:o->ch[1]->s);
if(k==s+1) return o->v;
else if(k<=s) return kth(o->ch[1],k);
else return kth(o->ch[0],k-s-1);
}
void IstTree(Node* &src,Node* &dest)
{
if(src->ch[0]!=NULL) IstTree(src->ch[0],dest);
if(src->ch[1]!=NULL) IstTree(src->ch[1],dest);
insert(dest,src->v);
delete src;
src=NULL;
}
void RmvTree(Node* &o)
{
if(o->ch[0]!=NULL) RmvTree(o->ch[0]);
if(o->ch[1]!=NULL) RmvTree(o->ch[1]);
delete o;
o=NULL;
}
void AddEdge(int x)
{
int u=ff(f[x]),v=ff(t[x]);
if(u!=v)
{
if(root[u]->s < root[v]->s)
{
fa[u]=v;
IstTree(root[u],root[v]);
}
else
{
fa[v]=u;
IstTree(root[v],root[u]);
}
}
}
int qcnt;
long long qtot;
void query(int x,int k)
{
qcnt++;
qtot+=kth(root[ff(x)],k);
}
void ChangeWeight(int x,int v)
{
int u=ff(x);
remove(root[u],w[x]);
insert(root[u],v);
w[x]=v;
}
int main()
{
#ifdef local
freopen("pro.in","r",stdin);
#endif
int kase=0;
while(scanf("%d%d",&n,&m)==2&&n)
{
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
for(int i=1;i<=m;i++) scanf("%d%d",&f[i],&t[i]);
memset(rmvd,0,sizeof(rmvd));
int c=0;
while(1)
{
char type;
int x,p=0,v=0;
scanf(" %c",&type);
if(type=='E') break;
scanf("%d",&x);
if(type=='D') rmvd[x]=true;
if(type=='Q') scanf("%d",&p);
if(type=='C')
{
scanf("%d",&v);
p=w[x];
w[x]=v;
}
cmds[c++]=(Command){type,x,p};
}
for(int i=1;i<=n;i++)
{
fa[i]=i;
if(root[i]!=NULL) RmvTree(root[i]);
root[i]=new Node(w[i]);
}
for(int i=1;i<=m;i++)
if(!rmvd[i]) AddEdge(i);
qtot=qcnt=0;
for(int i=c-1;i>=0;i--)
{
if(cmds[i].type=='D') AddEdge(cmds[i].x);
if(cmds[i].type=='Q') query(cmds[i].x,cmds[i].p);
if(cmds[i].type=='C') ChangeWeight(cmds[i].x,cmds[i].p);
}
printf("Case %d: %.6lf\n",++kase,qtot/(double)qcnt);
}
return 0;
}