A
艹居然被卡常了,100->50
這貌似是原題的加強版
加個hash亂搞一下就能過了
代碼:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return f?ans:-ans;
}
typedef pair<int,int> pii;
const int mogic=1e6+7,N=1e5+5,M=5e5+5;
int n,m,Ask;
struct Hash_table1{
vector<pii>ori[mogic];
vector<int>idx[mogic];
int tot;
Hash_table1(){tot=0;}
inline void update(const pii&a){
int t=((ll)a.fi%mogic*n%mogic+a.se)%mogic;
for(ri i=ori[t].size()-1;~i;--i)if(ori[t][i]==a)return;
ori[t].push_back(a),idx[t].push_back(++tot);
}
inline int query(const pii&a){
int t=((ll)a.fi%mogic*n%mogic+a.se)%mogic;
for(ri i=ori[t].size()-1;~i;--i)if(ori[t][i]==a)return idx[t][i];
}
}S1;
struct Hash_table2{
vector<int>ori[mogic],idx[mogic];
int tot;
Hash_table2(){tot=0;}
inline void update(const int&a){
int t=a%mogic;
for(ri i=ori[t].size()-1;~i;--i)if(ori[t][i]==a)return;
ori[t].push_back(a),idx[t].push_back(++tot);
}
inline int query(const int&a){
int t=a%mogic;
for(ri i=ori[t].size()-1;~i;--i)if(ori[t][i]==a)return idx[t][i];
}
}S2;
struct edge{int u,v,w;}e[M];
int pre1[M],all,col,sum=0,sig=0,qry[M];
vector<int>vis,ft2,vl2,rev2,siz2;
vector<edge>upd3[M<<2];
edge upd1[M];
struct stk4{
vector<pii>Ft,Siz,Rev;
inline void imodify(){
pii x=Ft.back();
Ft.pop_back();
ft2[x.fi]=x.se;
x=Siz.back();
Siz.pop_back();
siz2[x.fi]=x.se;
x=Rev.back();
Rev.pop_back();
rev2[x.fi]=x.se;
}
}q4;
struct Stk5{
vector<int>Vl;
inline void imodify(){
int x=Vl.back();
Vl.pop_back();
vl2[x]=0;
--sum;
}
}q5;
struct Stk3{
vector<int>Vis;
inline void imodify(){
int x=Vis.back();
Vis.pop_back();
vis[x]=0;
--sig;
}
}q3;
inline pii find2(int x){
if(x==ft2[x])return pii(x,rev2[x]);
pii t=find2(ft2[x]);
return pii(t.fi,t.se^rev2[x]);
}
inline void addedge2(edge a){
int x=S1.query(pii(a.w,a.u)),y=S1.query(pii(a.w,a.v)),coll=S2.query(a.w);
if(vl2[coll])return;
pii fx=find2(x),fy=find2(y);
if(!vis[coll]){
q3.Vis.push_back(coll);
vis[coll]=1;
++sig;
}
if(fx.fi^fy.fi){
if(siz2[fx.fi]<siz2[fy.fi])swap(fx,fy);
q4.Ft.push_back(pii(fy.fi,ft2[fy.fi])),ft2[fy.fi]=fx.fi;
q4.Siz.push_back(pii(fx.fi,siz2[fx.fi])),siz2[fx.fi]+=siz2[fy.fi];
q4.Rev.push_back(pii(fy.fi,rev2[fy.fi]));
if(fx.se==fy.se)rev2[fy.fi]^=1;
return;
}
else if(fx.se==fy.se){
q5.Vl.push_back(coll);
vl2[coll]=1;
++sum;
}
}
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (l+r>>1)
int cnt=0;
inline void update3(int p,int l,int r,int ql,int qr,edge v){
if(ql>qr)return;
if(ql<=l&&r<=qr){upd3[p].push_back(v);return;}
if(qr<=mid)update3(lc,l,mid,ql,qr,v);
else if(ql>mid)update3(rc,mid+1,r,ql,qr,v);
else update3(lc,l,mid,ql,qr,v),update3(rc,mid+1,r,ql,qr,v);
}
inline void solve(int p,int l,int r){
int cur3=q3.Vis.size(),cur4=q4.Ft.size(),cur5=q5.Vl.size();
for(ri i=0,up=upd3[p].size();i<up;++i)addedge2(upd3[p][i]);
if(l==r){
if(~qry[l]){
cout<<(vl2[S2.query(qry[l])]?"NO\n":"YES\n");
if(upd1[l].u)addedge2(upd1[l]);
cout<<sig-sum<<'\n';
}
while(q3.Vis.size()!=cur3)q3.imodify();
while(q4.Ft.size()!=cur4)q4.imodify();
while(q5.Vl.size()!=cur5)q5.imodify();
return;
}
solve(lc,l,mid),solve(rc,mid+1,r);
while(q3.Vis.size()!=cur3)q3.imodify();
while(q4.Ft.size()!=cur4)q4.imodify();
while(q5.Vl.size()!=cur5)q5.imodify();
}
#undef lc
#undef rc
#undef mid
struct Qry{
int op,a,b;
}Q[M];
int main(){
#ifdef ldxcaicai
freopen("lx.in","r",stdin);
freopen("std.out","w",stdout);
#endif
n=read(),m=read(),Ask=read();
for(ri w,u,v,i=1;i<=m;++i){
w=read(),u=read(),v=read();
S1.update(pii(w,u)),S1.update(pii(w,v));
S2.update(w);
e[i]=(edge){u,v,w};
pre1[i]=1;
}
int tot=0;
for(ri i=1;i<=Ask;++i){
Q[i].op=read();
Q[i].a=read();
if(!Q[i].op)Q[i].b=read(),++tot;
}
for(ri i=1,a,b,cnt=0;i<=Ask;++i){
a=Q[i].a,b=Q[i].b;
if(!Q[i].op){
++cnt;
qry[cnt]=a;
if(b){
update3(1,1,tot,pre1[b],cnt-1,e[b]);
upd1[cnt]=e[b];
pre1[b]=cnt+1;
}
S2.update(a);
}
else{
b=Q[i].a,a=Q[i].op;
update3(1,1,tot,pre1[a],cnt,e[a]);
pre1[a]=cnt+1,e[a].w=b;
S1.update(pii(e[a].w,e[a].u));
S1.update(pii(e[a].w,e[a].v));
S2.update(e[a].w);
}
}
for(ri i=1;i<=m;++i)update3(1,1,tot,pre1[i],tot,e[i]);
all=S1.tot,col=S2.tot;
vis.resize(col+1);
ft2.resize(all+1),siz2.resize(all+1),rev2.resize(all+1);
vl2.resize(col+1);
for(ri i=1;i<=all;++i)ft2[i]=i,siz2[i]=1,rev2[i]=0;
solve(1,1,tot);
return 0;
}
B
暫時咕掉
留坑
C
如果是棵樹就是點分治+ntt板題,現在變成了基環樹,由於保證環上的點很少因此可以暴力枚舉子樹的貢獻。
代碼:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
const int mod=1004535809;
typedef long long ll;
typedef vector<int> poly;
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?a:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))if(p&1)Mul(ret,a);return ret;}
int w[21],invv[21];
vector<int>rev[21];
inline void init_w(){
w[20]=ksm(3,(mod-1)>>21),invv[0]=1;
for(ri i=19;~i;--i)w[i]=mul(w[i+1],w[i+1]);
for(ri i=1,iv=mod+1>>1;i<21;++i)invv[i]=mul(invv[i-1],iv);
}
int lim,tim;
inline void init(const int&up){
lim=1,tim=0;
while(lim<up)lim<<=1,++tim;
if(rev[tim].size())return;
rev[tim].resize(lim);
for(ri i=1;i<lim;++i)rev[tim][i]=(rev[tim][i>>1]>>1)|((i&1)<<(tim-1));
}
inline void ntt(poly&a,const int&type){
for(ri i=0;i<lim;++i)if(i<rev[tim][i])swap(a[i],a[rev[tim][i]]);
for(ri i=1,t=0,a0,a1;i<lim;i<<=1,++t)for(ri j=0,len=i<<1;j<lim;j+=len)
for(ri k=0,mt=1;k<i;++k,Mul(mt,w[t]))a0=a[j+k],a1=mul(mt,a[j+k+i]),a[j+k]=add(a0,a1),a[j+k+i]=dec(a0,a1);
if(~type)return;
reverse(++a.begin(),a.end());
for(ri i=0;i<lim;++i)Mul(a[i],invv[tim]);
}
inline poly operator*(poly a,poly b){
int n=a.size(),m=b.size(),t=n+m-1;
if(t<=128){
poly c(t);
for(ri i=0;i<n;++i)for(ri j=0;j<m;++j)Add(c[i+j],mul(a[i],b[j]));
return c;
}
init(t);
a.resize(lim),ntt(a,1);
b.resize(lim),ntt(b,1);
for(ri i=0;i<lim;++i)Mul(a[i],b[i]);
return ntt(a,-1),a.resize(t),a;
}
const int N=1e5+5;
int n,top=0,stk[N],cnt[N],siz[N];
vector<int>e[N],lp;
bool in[N];
vector<poly>lopdis;
void findloop(int p,int fa){
in[p]=1,stk[++top]=p;
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa)continue;
if(in[v]){
if(lp.size())continue;
int t=top;
while(1){
lp.push_back(stk[t]);
if(stk[t]==v)break;
--t;
}
continue;
}
findloop(v,p);
}
in[p]=0,--top;
}
double ans=0;
int cnt1[N],cnt2[N],mxdep,alldep,all,rt,msz;
void getsize(int p,int fa){
siz[p]=1;
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa||in[v])continue;
getsize(v,p),siz[p]+=siz[v];
}
}
void getroot(int p,int fa){
siz[p]=1;
int ms=0;
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa||in[v])continue;
getroot(v,p),siz[p]+=siz[v];
ms=max(ms,siz[v]);
}
if((ms=max(ms,all-siz[p]))<msz)msz=ms,rt=p;
}
void getdist(int p,int fa,int dist){
++cnt2[dist],mxdep=max(mxdep,dist);
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa||in[v])continue;
getdist(v,p,dist+1);
}
}
inline void update_ans(poly a,int ad,int coe){for(ri i=a.size()-1;i;--i)if(a[i])ans+=1.0*coe*a[i]/(i+ad);}
inline void update(){
poly a,b;
a.resize(alldep+1),b.resize(mxdep+1);
for(ri i=1;i<=alldep;++i)a[i]=cnt1[i];
alldep=max(alldep,mxdep+1);
for(ri i=1;i<=mxdep;++i)cnt1[i+1]+=(b[i]=cnt2[i]),cnt2[i]=0;
update_ans(a*b,0,1);
}
void solve(int p,bool f){
in[p]=1;
for(ri i=1;i<=alldep;++i)cnt1[i]=0;
alldep=1,cnt1[1]=1;
for(ri i=0,v;i<e[p].size();++i){
if(in[v=e[p][i]])continue;
mxdep=0;
getdist(v,p,1);
update();
}
getsize(p,0);
for(ri i=0,v;i<e[p].size();++i){
if(in[v=e[p][i]])continue;
all=msz=siz[v],rt=0;
getroot(v,p),solve(rt,0);
}
}
int main(){
init_w();
n=read();
for(ri i=1,u,v;i<=n;++i){
u=read(),v=read();
e[u].push_back(v),e[v].push_back(u);
}
findloop(1,0);
for(ri i=lp.size()-1;~i;--i)in[lp[i]]=1;
lopdis.resize(lp.size());
for(ri i=lp.size()-1;~i;--i){
in[lp[i]]=0;
mxdep=0;
getdist(lp[i],0,1);
lopdis[i].resize(mxdep+1);
for(ri j=1;j<=mxdep;++j)lopdis[i][j]=cnt2[j],cnt2[j]=0;
getsize(lp[i],0);
rt=0,all=msz=siz[lp[i]];
getroot(lp[i],0),solve(rt,1);
in[lp[i]]=1;
}
double t=ans;
for(ri a,b,i=lp.size()-1;~i;--i)for(ri j=i-1;~j;--j){
a=i-j-1,b=lp.size()-i+j-1;
poly t=lopdis[i]*lopdis[j];
update_ans(t,a,1);
update_ans(t,b,1);
update_ans(t,a+b,-1);
}
printf("%.6lf",ans*2.0/n+1);
return 0;
}
考試總結:
的部分分寫錯也挺讓人無語的吧(雖然檢查過
被卡常搞得我徹底自閉了(本地挺快的不知道WSM被老爺機卡了
那個套路完全不會,現在到一種新技能QvQ