Day1T2
题解
集合求交,求并维护时间戳,整体+,-维护一个变量
其实都挺套路的,但我考场什么都没想到,竟然还有60
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 3444444 const ll sz=5000000; ll a[sz]; ll *b=a+2500000; ll ans,m,opt,mark,n,k,size,T=1; int main(){ // freopen("ex_jihe3.in","r",stdin); // freopen("zj.out","w",stdout); scanf("%lld",&m); for(ll i=1;i<=m;i++){ scanf("%lld",&opt); if(opt==1){ scanf("%lld",&k); for(ll i=1;i<=k;i++){ scanf("%lld",&n); if(b[n-mark]!=T){ b[n-mark]=T; ans+=n-mark; size++; } } } else if(opt==2){ ++T;ans=0;size=0; scanf("%lld",&k); for(ll i=1;i<=k;i++){ scanf("%lld",&n); if(b[n-mark]==T-1){ b[n-mark]=T; ans+=n-mark; size++; // printf("n-mark=%lld sz=%lld ",n-mark,size); } } } else if(opt==3){ mark++; } else if(opt==4){ mark--; } printf("%lld ",ans+mark*size); } }
Day1T3
题解
部分分有一部分是$C_m^2$提示
我们其他也可以这么做,找到每一个极大联通空地同时联通相同颜色每一对都会造成贡献
但是这样会有多个联通的情况
可能会出现最多会出现两个颜色之间四联通,会算重
必须容斥
记录下每个块被那个极大联通空地链接
f1[x][col]记录被x连接颜色为col的情况
f2[x][y][col]记录被x,y两个联通块链接颜色为col的情况
f3[x][y][z][col],f4[w][x][y][z][col]
奇加偶减,f1,f2,f3,f4用map存一下即可
相邻单独考虑
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 1111 struct node{ ll bl1,bl2,bl3,bl4,col; node(){} node(const ll &a,const ll &b,const ll &c,const ll &d,const ll &e){ bl1=a,bl2=b,bl3=c,bl4=d,col=e; } friend bool operator < (const node &a,const node &b){ if(a.bl1!=b.bl1) return a.bl1<b.bl1; if(a.bl2!=b.bl2) return a.bl2<b.bl2; if(a.bl3!=b.bl3) return a.bl3<b.bl3; if(a.bl4!=b.bl4) return a.bl4<b.bl4; return a.col<b.col; } }; map<node,ll> mp; ll bl[5][A][A],vis[A][A],col[A][A]; ll nowx[5]={0,1,-1,0,0}; ll nowy[5]={0,0,0,1,-1}; ll n,m,k,tim,ans; void dfs(ll x,ll y){ vis[x][y]=tim; if(col[x][y]){ if(!bl[1][x][y]) bl[1][x][y]=tim; else if(!bl[2][x][y]) bl[2][x][y]=tim; else if(!bl[3][x][y]) bl[3][x][y]=tim; else if(!bl[4][x][y]) bl[4][x][y]=tim; return ; } for(ll i=1;i<=4;i++){ ll xnow=nowx[i]+x,ynow=nowy[i]+y; if(xnow>=1&&xnow<=n&&ynow>=1&&ynow<=m&&vis[xnow][ynow]!=tim){ dfs(xnow,ynow); } } } int main(){ // freopen("ex_link4.in","r",stdin); ll kk; scanf("%lld%lld%lld",&n,&m,&kk); for(ll i=1;i<=n;i++) for(ll j=1;j<=m;j++) scanf("%lld",&col[i][j]); for(ll i=1;i<=n;i++) for(ll j=1;j<=m;j++){ if(!vis[i][j]&&col[i][j]==0){ tim++; dfs(i,j); } } for(ll i=1;i<=n;i++) for(ll j=1;j<=m;j++) if(col[i][j]){ if(bl[1][i][j]){ ans+=mp[node(bl[1][i][j],0,0,0,col[i][j])]++; } if(bl[2][i][j]){ ans+=mp[node(bl[2][i][j],0,0,0,col[i][j])]++; ans-=mp[node(bl[1][i][j],bl[2][i][j],0,0,col[i][j])]++; } if(bl[3][i][j]){ ans+=mp[node(bl[3][i][j],0,0,0,col[i][j])]++; ans-=mp[node(bl[2][i][j],bl[3][i][j],0,0,col[i][j])]++; ans-=mp[node(bl[1][i][j],bl[3][i][j],0,0,col[i][j])]++; ans+=mp[node(bl[1][i][j],bl[2][i][j],bl[3][i][j],0,col[i][j])]++; } if(bl[4][i][j]){ ans+=mp[node(bl[4][i][j],0,0,0,col[i][j])]++; ans-=mp[node(bl[1][i][j],bl[4][i][j],0,0,col[i][j])]++; ans-=mp[node(bl[2][i][j],bl[4][i][j],0,0,col[i][j])]++; ans-=mp[node(bl[3][i][j],bl[4][i][j],0,0,col[i][j])]++; ans+=mp[node(bl[1][i][j],bl[2][i][j],bl[4][i][j],0,col[i][j])]++; ans+=mp[node(bl[1][i][j],bl[3][i][j],bl[4][i][j],0,col[i][j])]++; ans+=mp[node(bl[2][i][j],bl[3][i][j],bl[4][i][j],0,col[i][j])]++; ans-=mp[node(bl[1][i][j],bl[2][i][j],bl[3][i][j],bl[4][i][j],col[i][j])]++; } // printf("%lld bl 4=%lld 3=%lld 2=%lld 1=%lld ",ans,bl[4][i][j],bl[3][i][j],bl[2][i][j],bl[1][i][j]); } // printf("%lld ",ans); for(ll i=1;i<=n;i++) for(ll j=2;j<=m;j++) if(col[i][j-1]&&col[i][j]&&col[i][j]==col[i][j-1]){ ll ok=1; for(ll k=1;k<=4;k++) for(ll e=1;e<=4;e++) if(bl[k][i][j]&&bl[e][i][j-1]&&bl[k][i][j]==bl[e][i][j-1]) ok=0; ans+=ok; } for(ll i=2;i<=n;i++) for(ll j=1;j<=m;j++) if(col[i-1][j]&&col[i][j]&&col[i][j]==col[i-1][j]){ ll ok=1; for(ll k=1;k<=4;k++) for(ll e=1;e<=4;e++) if(bl[k][i][j]&&bl[e][i-1][j]&&bl[k][i][j]==bl[e][i-1][j]) ok=0; ans+=ok; } printf("%lld ",ans); }
Day2T3
题解
假设环上点为黑点,其他点为白点,我们现在要统计的就是max(白点到最近黑点距离)
假设黑点中深度最小的为B
开这样几个数组ff[x]表示从x走到父亲后能走到最远距离
g[x]表示从x向下走到距离最远是多少
然而可能有最多两个黑点将路径堵塞,所以记录最大值,次大值,次次大值,
黑点即使将最大值次大值堵上,你可以走次次大值
然后贡献可以分为两部分
每个黑点g,最上点ff
这样复杂度仍然会炸
考虑优化求每个黑点g
发现lca路径上除了lca其他点只和一个儿子黑点相邻
q[x]表示从x走到父亲路径上向下走但不经过x达到最远点
然后倍增优化一下
现在贡献变成g[lca],g[x],g[y],q[lca路径上],ff[lca]
分别维护一下
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 1111111 ll n,tot=1,tim,m,t; ll head[A],ver[A],nxt[A],du[211111],deep[A],qjdis[A],zj[A]; ll maxcost[A][25],f[A][25]; ll ans=0; pair<ll,ll>g[A][3],dis[A],ff[A],q[A][25]; pair<ll,ll>tmp; void add(ll x,ll y){ nxt[++tot]=head[x],head[x]=tot,ver[tot]=y; } ll lca(ll x,ll y){ pair<ll,ll> pr;ll now=0; pr=make_pair(0,0); if(deep[x]>deep[y]) swap(x,y); ll lastx=x,lasty=y; for(ll i=t;i>=0;i--){ if(deep[x]==deep[y]) break; if(deep[x]<=deep[f[y][i]]) { pr=max(pr,q[y][i]); y=f[y][i]; } } if(x==y) { ll lcq=x; return max(pr.first,max(ff[lcq].first,g[lasty][0].first)); } for(ll i=t;i>=0;i--){ if(f[x][i]!=f[y][i]) { pr=max(pr,q[x][i]); pr=max(pr,q[y][i]); x=f[x][i],y=f[y][i]; } } ll lcq=f[x][0]; if((g[lcq][0].second==x&&g[lcq][1].second==y)||(g[lcq][1].second==x&&g[lcq][0].second==y)){ now=max(g[lcq][2].first,pr.first); } else if((g[lcq][0].second==x&&g[lcq][1].second!=y)||(g[lcq][0].second==y&&g[lcq][1].second!=x)){ now=max(g[lcq][1].first,pr.first); } else { now=max(g[lcq][0].first,pr.first); } now=max(now,ff[lcq].first); now=max(now,max(g[lastx][0].first,g[lasty][0].first)); return now; } pair<ll,ll> dfs1(ll x,ll pre){ dis[x]=make_pair(0,0); for(ll i=head[x];i;i=nxt[i]){ ll y=ver[i]; if(y==pre) continue ; f[y][0]=x; deep[y]=deep[x]+1; pair<ll,ll> d=dfs1(y,x); dis[x]=max(dis[x],d); } return make_pair(dis[x].first+1,dis[x].second); } void dfs2(ll x,ll pre){ pair<ll,ll> fir,sec,thi,tmp; for(ll i=head[x];i;i=nxt[i]){ ll y=ver[i]; if(y==pre) continue ; if((dis[y].first+1)>fir.first){ thi=sec;sec=fir;fir=make_pair(dis[y].first+1,y); } else if((dis[y].first+1)>sec.first){ thi=sec; sec=make_pair(dis[y].first+1,y); } else if((dis[y].first+1)>thi.first){ thi=make_pair(dis[y].first+1,y); } } g[x][0]=make_pair(fir.first,fir.second); g[x][1]=make_pair(sec.first,sec.second); g[x][2]=make_pair(thi.first,thi.second); for(ll i=head[x];i;i=nxt[i]){ ll y=ver[i]; if(y==pre) continue ; if(dis[y].first+1==fir.first) q[y][0]=sec; else q[y][0]=fir; } for(ll i=head[x];i;i=nxt[i]){ ll y=ver[i]; if(y==pre) continue ; dfs2(y,x); } } void redfs(ll x,ll pre){ for(ll i=head[x];i;i=nxt[i]){ ll y=ver[i]; if(y==pre) continue ; ff[y]=ff[x]; if(y==g[x][0].second) ff[y]=max(ff[y],g[x][1]); else ff[y]=max(ff[y],g[x][0]); ff[y]=make_pair(ff[y].first+1,ff[y].second); } for(ll i=head[x];i;i=nxt[i]){ ll y=ver[i]; if(y==pre) continue ; redfs(y,x); } } void dfs3(ll x,ll pre){ for(ll i=head[x];i;i=nxt[i]){ ll y=ver[i]; if(y==pre) continue ; dfs3(y,x); ans=max(zj[x]+zj[y]+1,ans); zj[x]=max(zj[x],zj[y]+1); } } int main(){ scanf("%lld",&n); t=log(n)/log(2)+1; for(ll i=1;i<n;i++){ ll a,b; scanf("%lld%lld",&a,&b); add(a,b); add(b,a); } dfs1(1,0); dfs2(1,0); dfs3(1,0); redfs(1,0); f[1][0]=1; for(ll j=1;j<=t;j++){ for(ll i=1;i<=n;i++){ f[i][j]=f[f[i][j-1]][j-1]; q[i][j]=max(q[f[i][j-1]][j-1],q[i][j-1]); } } scanf("%lld",&m); for(ll i=1;i<=m;i++){ ll a,b; scanf("%lld%lld",&a,&b); if(a==b){ printf("%lld ",(ans)/2+1); continue ; } printf("%lld ",lca(a,b)); } }