【2019.9.16】Za
天天爱跑步
树上差分
咕==
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10,M=50000+10,inf=0x3f3f3f3f;
int n,m,w[N],ans[N],c1[N<<1],c2[N<<1];
vector<int>a1[N],b1[N],a2[N],b2[N];
template <class t>void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int head[N],tot=0;
struct edge{int v,nxt;}e[N<<1];
void add(int u,int v){e[++tot]=(edge){v,head[u]},head[u]=tot;}
int dep[N],f[N][25];
void bfs(int u,int fa){
dep[u]=dep[fa]+1,f[u][0]=fa;
for(int i=head[u],v;i;i=e[i].nxt)
if((v=e[i].v)!=fa) bfs(v,u);
}
void prepare(){
bfs(1,0);
for(int i=1;i<=20;++i)
for(int j=1;j<=n;++j)
f[j][i]=f[f[j][i-1]][i-1];
}
int LCA(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=20;i>=0;--i)
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
if(x==y) return x;
for(int i=20;i>=0;--i)
if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
bool vis[N];
void dfs(int x){
int w1=c1[dep[x]+w[x]],w2=c2[w[x]-dep[x]+n];
vis[x]=1;
for(int i=head[x],v;i;i=e[i].nxt)
if(!vis[v=e[i].v]) dfs(v);
for(int i=0;i<a1[x].size();++i) ++c1[a1[x][i]];
for(int i=0;i<b1[x].size();++i) --c1[b1[x][i]];
for(int i=0;i<a2[x].size();++i) ++c2[a2[x][i]+n];
for(int i=0;i<b2[x].size();++i) --c2[b2[x][i]+n];
ans[x]+=c1[dep[x]+w[x]]-w1+c2[w[x]-dep[x]+n]-w2;
}
int main(){
freopen("in.txt","r",stdin);
rd(n),rd(m);
for(int i=1,u,v;i<n;++i) rd(u),rd(v),add(u,v),add(v,u);
for(int i=1;i<=n;++i) rd(w[i]);
prepare();
for(int i=1,x,y,z;i<=m;++i){
rd(x),rd(y),z=LCA(x,y);
a1[x].push_back(dep[x]),
a2[y].push_back(dep[x]-(dep[z]<<1)),
b1[f[z][0]].push_back(dep[x]),
b2[z].push_back(dep[x]-(dep[z]<<1));
}
dfs(1);
for(int i=1;i<=n;++i) printf("%d ",ans[i]);
return 0;
}
求桥
void tarjan(int u,int ine){
dfn[u]=low[u]=++idx;
for(int i=head[u],v;i;i=e[i].nxt){
if(!dfn[v=e[i].v]) {
tarjan(v,i),low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]) bridge[i]=bridge[i^1]=1;
}
else if(i!=(ine^1)) low[u]=min(low[u],dfn[v]);
}
}
求割点
void tarjan(int u){
dfn[u]=low[u]=++idx;int kid=0;
for(int i=head[u],v;i;i=e[i].nxt){
if(!dfn[v=e[i].v]){
tarjan(v),low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])
if(++kid>1||u!=rt) cut[u]=1;
}
else low[u]=min(low[u],dfn[v]);
}
}
边双连通e-DCC
void tarjan(int u,int ine){
dfn[u]=low[u]=++idx;
for(int i=head[u],v;i;i=e[i].nxt){
if(!dfn[v=e[i].v]) {
tarjan(v,i),low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]) bridge[i]=bridge[i^1]=1;
}
else if(i!=(ine^1)) low[u]=min(low[u],dfn[v]);
}
}
int bl[N],dcc;
void dfs(int x){
bl[x]=dcc;
for(int i=head[u],v;i;i=e[i].nxt)
if(!bl[v=e[i].v]&&!bridge[i]) dfs(v);
}
int main(){
for(int i=1;i<=n;++i)
if(!bl[i]) ++dcc,dfs(i);
return 0;
}
点双连通v-DCC
void tarjan(int u){
dfn[u]=low[u]=++idx,s.push(u);
if(u==rt&&!head[u]) dcc[++cnt].push_back(u);
int kid=0;
for(int i=head[u],v,;i;i=e[i].nxt){
if(!dfn[v=e[i].v]){
tarjan(v),low[u]=min(low[u],low[v]);
if(low[v]>=low[u]){
if(++kid>1||u!=rt) cut[u]=1;
++cnt;int z;
do{
z=s.top(),s.pop();
dcc[cnt].push_back(z);
}while(z!=v)
dcc[cnt].push_back(u);
}
else low[u]=min(low[u],dfn[v]);
}
}
}
[JSOI2010] 连通数
缩点完后用bitset来统计==
按拓扑序来
#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
const int N=2000+10,M=4000000+10,inf=0x3f3f3f3f;
int n;
char ss[N];
bitset<N>f[N];
template <class t>void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int head[N],hd[N],tot=0,tt=0;
struct edge{int v,nxt;}e[M],E[M];
void Add(int u,int v){E[++tt]=(edge){v,hd[u]},hd[u]=tt;}
void add(int u,int v){e[++tot]=(edge){v,head[u]},head[u]=tot;}
int idx=0,Bcnt=0,dfn[N],low[N],bl[N],sz[N];
stack<int>s;bool inst[N];
void tarjan(int u){
dfn[u]=low[u]=++idx,s.push(u),inst[u]=1;
for(int i=head[u],v;i;i=e[i].nxt)
if(!dfn[v=e[i].v]) tarjan(v),low[u]=Min(low[u],low[v]);
else if(inst[v]&&dfn[v]<low[u]) low[u]=dfn[v];
if(dfn[u]==low[u]){
++Bcnt;int v;
do{
v=s.top(),s.pop(),inst[v]=0,f[Bcnt].set(v);
bl[v]=Bcnt,++sz[Bcnt];
}while(u!=v);
}
}
int Q[N],in[N];
queue<int>q;
void topsort(){
for(int i=1;i<=Bcnt;++i) if(!in[i]) q.push(i);
while(!q.empty()){
int u=q.front();
q.pop(),Q[++Q[0]]=u;
for(int i=hd[u],v;i;i=E[i].nxt)
if(!--in[v=E[i].v]) q.push(v);
}
for(int i=Q[0];i;--i)
for(int j=hd[Q[i]];j;j=E[j].nxt)
f[Q[i]]|=f[E[j].v];
}
int main(){
freopen("in.txt","r",stdin);
rd(n);
for(int i=1;i<=n;++i){
scanf("%s",ss+1);
for(int j=1;j<=n;++j)
if(ss[j]=='1') add(i,j);
}
for(int i=1;i<=n;++i)
if(!dfn[i]) tarjan(i);
for(int u=1,v;u<=n;++u)
for(int i=head[u];i;i=e[i].nxt)
if(bl[u]!=bl[v=e[i].v]) Add(bl[u],bl[v]),++in[bl[v]];
int ans=0;
topsort();
for(int i=1;i<=Bcnt;++i) ans+=f[i].count()*sz[i];
printf("%d",ans);
return 0;
}
缩完点后topsort时DP
#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
const int N=100000+10,M=100000 +10,inf=0x3f3f3f3f;
int n,m,in[N];
template <class t>void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int head[N],hd[N],tot=0,tt=0;
struct edge{int v,w,nxt;}e[M],E[M<<1];
void Add(int u,int v,int w){E[++tt]=(edge){v,w,hd[u]},hd[u]=tt;}
void add(int u,int v,int w){e[++tot]=(edge){v,w,head[u]},head[u]=tot;}
int idx=0,Bcnt=0,dfn[N],low[N],bl[N],sz[N];
stack<int>s;bool inst[N];
void tarjan(int u){
dfn[u]=low[u]=++idx,s.push(u),inst[u]=1;
for(int i=head[u],v;i;i=e[i].nxt)
if(!dfn[v=e[i].v]) tarjan(v),low[u]=Min(low[u],low[v]);
else if(inst[v]&&dfn[v]<low[u]) low[u]=dfn[v];
if(low[u]==dfn[u]){
++Bcnt;int v;
do{
v=s.top(),s.pop(),inst[v]=0;
bl[v]=Bcnt,++sz[Bcnt];
}while(u!=v);
}
}
queue<int>q;
int f[N];
void topsort(){
q.push(0);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=hd[u],v;i;i=E[i].nxt){
f[v=E[i].v]=Max(f[v],f[u]+E[i].w);
if(!--in[v]) q.push(v);
}
}
long long ans=0;
for(int i=1;i<=Bcnt;++i) ans+=(long long)f[i]*sz[i];
printf("%lld",ans);
}
int main(){
freopen("in.txt","r",stdin);
rd(n),rd(m);
for(int i=1,opt,x,y;i<=m;++i){
rd(opt),rd(x),rd(y);
if(opt==1) add(x,y,0),add(y,x,0);
else if(opt==2) add(x,y,1);
else if(opt==3) add(y,x,0);
else if(opt==4) add(y,x,1);
else add(x,y,0);
}
for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
for(int u=1;u<=n;++u)
for(int i=head[u],v;i;i=e[i].nxt){
if(bl[u]==bl[v=e[i].v]&&e[i].w) return puts("-1"),0;
else if(bl[u]!=bl[v]) Add(bl[u],bl[v],e[i].w),++in[bl[v]];
}
for(int i=1;i<=Bcnt;++i) Add(0,i,1),++in[i];
topsort();
return 0;
}
[IOI2008]Island
我太难了 打的时候脑子里一团浆糊
acwing上面要T 洛谷上面可以过
#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define ll long long
const int N=1e6+10,M=100000 +10,inf=0x3f3f3f3f;
int n,in[N];
template <class t>void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int head[N],tot=0;
struct edge{int v,w,nxt;}e[N<<1];
void add(int u,int v,int w){
e[++tot]=(edge){v,w,head[u]},head[u]=tot,++in[v];
}
int bl[N],Bcnt=0;
queue<int>q;
void bfs(int u){
q.push(u);
while(!q.empty()){
u=q.front(),q.pop();
for(int i=head[u],v;i;i=e[i].nxt)
if(!bl[v=e[i].v]) bl[v]=Bcnt,q.push(v);
}
}
ll dis[N],f[N],a[N],b[N];
void topsort(){
for(int i=1;i<=n;++i) if(in[i]==1) q.push(i);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u],v;i;i=e[i].nxt)
if(in[v=e[i].v]>1){
dis[bl[u]]=Max(dis[bl[u]],f[u]+f[v]+e[i].w),
f[v]=Max(f[v],f[u]+e[i].w);
if((--in[v])==1) q.push(v);
}
}
}
int Q[N];
bool vis[N];
void dp(int x,int t)
{
int m=0,i,l=0,r,y=x;
do{
a[++m]=f[y];in[y]=1;
for(i=head[y];i;i=e[i].nxt)
if(in[e[i].v]>1)
{y=e[i].v;b[m+1]=b[m]+e[i].w; break;}
}while(i);
if(m==2)
{
for(i=head[y];i;i=e[i].nxt)
if(e[i].v==x) {l=max(l,e[i].w);}
dis[t]=max(dis[t],f[x]+f[y]+l);
return;
}
for(i=head[y];i;i=e[i].nxt)
if(e[i].v==x) {b[m+1]=b[m]+e[i].w; break;}
for(i=1;i<m;i++) {a[m+i]=a[i]; b[m+i]=b[m+1]+b[i];}
Q[l=r=1]=1;
for(i=2;i<2*m;i++)
{
while(l<=r&&i-Q[l]>=m) l++;
dis[t]=max(dis[t],a[i]+a[Q[l]]+b[i]-b[Q[l]]);
while(l<=r&&a[Q[r]]+b[i]-b[Q[r]]<=a[i]) r--;
Q[++r]=i;
}
}
int main(){
freopen("in.txt","r",stdin);
rd(n);ll ans=0;
for(int i=1,v,w;i<=n;++i) rd(v),rd(w),add(i,v,w),add(v,i,w);
for(int i=1;i<=n;++i)
if(!bl[i]) ++Bcnt,bfs(i);
topsort();
for(int i=1;i<=n;++i)
if(in[i]>1&&!vis[bl[i]]) vis[bl[i]]=1,dp(i,bl[i]),ans+=dis[bl[i]];
printf("%lld",ans);
return 0;
}