SDOI2018
Posted cszmc2004
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SDOI2018相关的知识,希望对你有一定的参考价值。
战略游戏
题目要求求删除后能使一些点不连通的点的个数。
删点可以想到点双树。
建出原图的点双树。
一条路径x,y上的点如果被删除,则x,y不能互相到达。
如果把圆点的权值设为1,方点的设为0,则答案就是虚树的点权和。
实际上,不用把虚树建出来。可以使用一个经典结论。
如果把一个点的权值放在父亲边上,则链的并的长度就是答案。
把点按照dfs序排序,最后添加dfs序最小的点。
则相邻两个点的距离加起来/2就是答案。
物理实验
原题识别
比较毒瘤的二维数点。
实际上不用计算期望,乘以对应的数后就变成了计数。
sub1直接树上莫队。
这和正解没有任何关系。要解决该题,需要发现如下随机性质:
1.颜色数期望(O(1))
2.两个点到lca的距离的min值期望log
先考虑第一问。
假设询问是(x,y),且x->lca的距离<=y->lca的距离。
使用可持久化线段树计算y->lca的点的颜色个数。
枚举x到lca的所有点,计算这个点的颜色是否在y->lca的路径上出现。
此部分时间复杂度期望(O(log_2n))。
链的做法是树的做法的简化版。
第二问可以分每个节点计算贡献。
根据数颜色经典套路,设(p_i)表示i节点前面第一个颜色相同的位置。
如果一个点(A< ileq B, p_ileq A),贡献((A-p_i)(B-i+1)),
如果一个点(1leq ileq A,xleq y),贡献((i-p_i)(B-i+1))
如果一个点(1leq ileq A,xgeq y),贡献((i-p_i)(A-i+1))
第二,三个贡献会多算(x=y),减掉(A)即可。
设(f)是x,y的lca
拆第一个贡献的式子。
(sum_{i=A+1,p_ileq A}^B (A-p_i)(B-i+1)\=A(B+1)sum 1-(B+1)sum p_i-Asum i+sum p_ii)
使用可持久化线段树维护(sum 1,sum p_i,sum i,sum p_ii)
拆第2,3个贡献的式子。
(sum_{i=1}^A (i-p_i)(B-i+1)+sum_{i=1}^A (i-p_i)(A-i+1)\=(A+B+2)sum (i-p_i)-2sum i(i-p_i))
使用前缀和维护(sum_{i=1}^A (i-p_i)(B-i+1)+sum_{i=1}^A (i-p_i)(A-i+1)\=(A+B+2)sum (i-p_i)-2sum i(i-p_i))
拓展到树上,前缀和/可持久化线段树从父亲转移到现在的点。
把问题划分成3个。
1.(xin [1,f),yin [1,B]),和链上的情况一样。
2.(xin [f,A],yin [1,f])
用(xin [1,A],yin [1,f))的贡献减去(xin [1,f),yin [1,f))的贡献。
(xin [1,A],yin [1,f))和链上的情况一样。
(xin [1,f),yin [1,f))的贡献是(sum_{i=1}^{f-1} (2(i-p_i)(f-i)-1))
3.(xin [f,A],yin [f,B])
先计算(iin [f,B])的贡献,是
(sum_{i=f,p_i< f}^B (B-i+1)(A-f+1))
再计算(iin (f,A])的贡献。
首先i要满足(p_ileq f)。设(j)为([f,B])中第一个和它颜色相同的点(若没有,则j=B+1)。那么贡献为((A?i+1)(j?f))。
代码很难写。
#include<bits/stdc++.h>
using namespace std;
#define N 200010
#define cv(x) memset(x,0,sizeof(x))
unsigned int sa, sb, sc;
unsigned int rng61(){
sa ^= sa << 16;
sa ^= sa >> 5;
sa ^= sa << 1;
unsigned int t = sa;
sa = sb;
sb = sc;
sc ^= t ^ sa;
return sc;
}
#define int long long
struct no{
int a,b,c,d;
}b[N*20];
no operator+(no x,no y){
return (no){x.a+y.a,x.b+y.b,x.c+y.c,x.d+y.d};
}
no operator-(no x,no y){
return (no){x.a-y.a,x.b-y.b,x.c-y.c,x.d-y.d};
}
int n,s,f[N],rt[N],lc[N*20],rc[N*20],h[N],v[N],nxt[N],ec,a[N],m,g[N][20],d[N],ct,p[N],bc[N],cc,in[N],ou[N],lg[N],s1[N],s2[N];
vector<int>cl[N];
void add(int x,int y){v[++ec]=y;nxt[ec]=h[x];h[x]=ec;}
void adj(int x,int y){add(x,y);add(y,x);}
int gd(int x,int y){
return d[x]<d[y]?x:y;
}
void ins(int &o,int p,int l,int r,int x,no y){
o=++ct;
b[o]=b[p]+y;
if(l==r)return;
int md=(l+r)/2;
if(x<=md){
rc[o]=rc[p];
ins(lc[o],lc[p],l,md,x,y);
}
else{
lc[o]=lc[p];
ins(rc[o],rc[p],md+1,r,x,y);
}
}
no qu(int o,int p,int l,int r,int x,int y){
if(r<x||y<l||x>y)
return(no){0,0,0,0};
if(x<=l&&r<=y)
return b[o]-b[p];
int md=(l+r)/2;
return qu(lc[o],lc[p],l,md,x,y)+qu(rc[o],rc[p],md+1,r,x,y);
}
void dfs(int x,int fa){
f[x]=fa;
d[x]=d[fa]+1;
g[x][0]=fa;
cc++;
in[x]=cc;
p[x]=bc[a[x]];
int lc=bc[a[x]];
bc[a[x]]=x;
s1[x]=s1[fa]+d[x]-d[p[x]];
s2[x]=s2[fa]+d[x]*(d[x]-d[p[x]]);
ins(rt[x],rt[f[x]],0,n,d[p[x]],(no){1,d[p[x]],d[x],d[p[x]]*d[x]});
for(int i=h[x];i;i=nxt[i])
if(v[i]!=fa)
dfs(v[i],x);
ou[x]=cc;
bc[a[x]]=lc;
}
int lca(int x,int y){
if(d[x]>d[y])swap(x,y);
for(int i=19;~i;i--)
if(d[g[y][i]]>=d[x])
y=g[y][i];
if(x==y)return x;
for(int i=19;~i;i--)
if(g[x][i]!=g[y][i])
x=g[x][i],y=g[y][i];
return g[x][0];
}
int di(int x,int y){
return d[x]+d[y]-2*d[lca(x,y)];
}
int pd(int x,int y,int z){
return in[x]<=in[z]&&in[z]<=ou[x]&&in[z]<=in[y]&&in[y]<=ou[z];
}
int qc(int x,int y){
if(d[x]>d[y])swap(x,y);
if(!x||!y)return 0;
int va=s1[x]*(d[x]+d[y]+2)-2*s2[x];
no v=qu(rt[y],rt[x],0,n,0,d[x]);
va+=d[x]*(d[y]+1)*v.a;
va-=(d[y]+1)*v.b;
va-=d[x]*v.c;
va+=v.d;
va-=d[x];
return va;
}
int q2(int x,int y){
int lc=lca(x,y),va=0;
if(di(x,lc)>di(y,lc))
swap(x,y);
va+=qc(f[lc],y);
int vv=qc(x,f[lc]);
vv-=-d[lc]+1+2*s1[f[lc]]*d[lc]-2*s2[f[lc]];
va+=vv;
no vg=qu(rt[y],rt[f[lc]],0,n,0,d[f[lc]]);
va+=vg.a*(d[x]-d[lc]+1+d[x]*d[y]-d[y]*d[lc]+d[y]);
va+=(d[lc]-1-d[x])*vg.c;
for(int i=x;i!=lc;i=f[i])
if(d[p[i]]<=d[lc]){
int j=d[y]+1;
for(int k:cl[a[i]])
if(pd(lc,y,k))
if(j>d[k])j=d[k];
va+=(d[x]-d[i]+1)*(j-d[lc]);
}
return va;
}
int q1(int x,int y){
int lc=lca(x,y),va;
if(di(x,lc)>di(y,lc))
swap(x,y);
va=qu(rt[y],rt[f[lc]],0,n,0,d[f[lc]]).a;
for(int i=x;i!=lc;i=f[i]){
int ok=1;
for(int j:cl[a[i]])
if(pd(lc,y,j))
ok=0;
va+=ok;
}
return va;
}
signed main(){
for(int i=2;i<N;i++)
lg[i]=lg[i>>1]+1;
int t;
cin>>t;
while(t--){
cv(f);
cv(rt);
for(int i=1;i<=ct;i++)
lc[i]=rc[i]=b[i].a=b[i].b=b[i].c=b[i].d=0;
cv(h);
cv(v);
cv(nxt);
ec=ct=cc=0;
cv(a);
cv(g);
cv(d);
cv(p);
cv(bc);
cv(in);
cv(ou);
cv(s1);
cv(s2);
cin>>n>>s>>sa>>sb>>sc;
for(int i = 2; i <= s; i++)
adj(i - 1, i);
for(int i = s + 1; i <= n; i++)
adj(rng61() % (i - 1) + 1, i);
int mxc=0;
for(int i = 1; i <= n; i++){
a[i] = rng61() % n + 1;
cl[a[i]].push_back(i);
mxc=max(mxc,a[i]);
}
cin>>m;
dfs(1,0);
g[1][0]=1;
for(int i=1;i<20;i++)
for(int j=1;j<=n;j++)
g[j][i]=g[g[j][i-1]][i-1];
while(m--){
if(!t){
t++;
t--;
}
int op,x,y;
cin>>op>>x>>y;
if(op==1)
cout<<q1(x,y)<<‘
‘;
else cout<<q2(x,y)<<‘
‘;
}
for(int i=1;i<=mxc;i++)
cl[i].clear();
}
}
旧试题
反回文串
荣誉称号
以上是关于SDOI2018的主要内容,如果未能解决你的问题,请参考以下文章