paths
斯坦纳树板题
呃,居然忘了自己会斯坦纳树,没看出来这是个板题?
乱搞拿了70…
#include<bits/stdc++.h>
using namespace std;
const int N=102,M=2005,inf=0x7f7f7f7f;
int n,m,K,ans,S,s,f[N][(1<<10)+10],g[(1<<10)+10];
int head[N],to[M],nxt[M],w[M],tot;
bool cn[(1<<10)+10];
char cp;
template<class T>inline void rd(T &x)
{
cp=getchar();x=0;int f=0;
for(;!isdigit(cp);cp=getchar()) if(cp=='-') f=1;
for(;isdigit(cp);cp=getchar()) x=x*10+(cp^48);
if(f) x=-x;
}
inline void lk(int u,int v,int vv)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;w[tot]=vv;}
inline void dn(int &x,int y){if(y<x) x=y;}
struct pr{
int x,v;
pr(int x_=0,int v_=0):x(x_),v(v_){};
bool operator <(const pr&ky)const{return v>ky.v;}
}tp;
priority_queue<pr>que;
inline void dij()
{
int i,j,x;
for(;!que.empty();){
tp=que.top();que.pop();x=tp.x;
if(f[x][s]!=tp.v) continue;
for(i=head[x];i;i=nxt[i]){
j=to[i];if(f[j][s]<=f[x][s]+w[i]) continue;
f[j][s]=f[x][s]+w[i];que.push(pr(j,f[j][s]));
}
}
}
int main(){
freopen("paths.in","r",stdin);
freopen("paths.out","w",stdout);
int i,j,x,y,z,t;memset(f,0x7f,sizeof(f));
rd(n);rd(m);rd(K);S=1<<K;
for(i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&z);
x--;y--;lk(x,y,z);lk(y,x,z);
}
for(i=0;i<K;++i) f[i][1<<i]=f[i][0]=0;
for(s=1;s<S;++s){
for(i=0;i<n;++i){
for(t=s&(s-1);t;t=(t-1)&s) if(f[i][t]<inf && f[i][s^t]<inf)
dn(f[i][s],f[i][t]+f[i][s^t]);
if(f[i][s]<inf) que.push(pr(i,f[i][s]));
}
dij();
}
for(i=0;i<S;++i){
for(j=0;j<K;j+=2) if(((i>>j)&1)^((i>>(j+1))&1)) break;
if(j>=K) cn[i]=true;
for(j=1;j<n;++j)
dn(f[0][i],f[j][i]);
}
memset(g,0x7f,sizeof(g));g[0]=0;
for(s=1;s<S;++s) if(cn[s])
for(t=s;t;t=(t-1)&s)
if(cn[t] && f[0][t]<inf && g[s^t]<inf)
dn(g[s],g[s^t]+f[0][t]);
printf("%d",g[S-1]);
fclose(stdin);fclose(stdout);
return 0;
}
*quiz
分块。
按下标分块,预处理 f i , j f_{i,j} fi,j表示点 i i i在第 j j j块的 s s s中被计算次数, s u m i sum_i sumi维护第 i i i块的 ∑ s \sum s ∑s, n \sqrt n n维护修改后的 s u m i sum_i sumi。
发现散块的单点计算依旧是 O ( n ) O(n) O(n)的,考虑再按dfs序分块维护 w w w的前缀和(整块/块内), n \sqrt n n维护修改后的前缀和。
在询问时,整块可以 s u m sum sum求,散块暴力遍历,并用dfs序的分块 O ( 1 ) O(1) O(1)回答 s s s值。
总复杂度 O ( n n ) O(n\sqrt n) O(nn)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e5+10,M=322;
int n,m,rt,val[N],c[N];
int df[N],ot[N],dfn,rv[N];
int head[N],to[N<<1],nxt[N<<1],tot;
struct qr{int op,l,r;}q[N];
char cp;
template<class T>inline void rd(T &x)
{
cp=getchar();x=0;int f=0;
for(;!isdigit(cp);cp=getchar()) if(cp=='-') f=1;
for(;isdigit(cp);cp=getchar()) x=x*10+(cp^48);
if(f) x=-x;
}
template<class T>inline void prit(T x)
{if(x>9) prit(x/10);putchar('0'+(x%10));}
inline void lk(int u,int v)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
void dfs(int x,int fr)
{
int i,j,k;df[x]=++dfn;rv[dfn]=x;
for(i=head[x];i;i=nxt[i]){
j=to[i];if(j==fr) continue;
dfs(j,x);
}
ot[x]=dfn;
}
namespace FK{
int blk,f[N][M],bel[N],cot;
ull sum[M],ss[M][M];
inline void chg(int x,int y)
{
int i,j,k,l,r,dlt=y-val[x];
for(i=1;i<=cot;++i) sum[i]+=(ll)f[x][i]*dlt;
i=bel[df[x]];l=(i-1)*blk+1;r=min(i*blk,n);
for(j=df[x]-l+1;l+j-1<=r;++j) ss[i][j]+=dlt;
for(j=i;j<=cot;++j) ss[j][0]+=dlt;
val[x]=y;
}
inline ull query(int l,int r)
{
int L=bel[l],R=bel[r],i,j;ull re=0;
if(L+1<R) re+=(ss[R-1][0]-ss[L][0]);
i=(L-1)*blk;j=min(n,L*blk);re+=ss[L][min(r,j)-i];
if(l!=i+1) re-=ss[L][l-i-1];
if(L!=R) re+=ss[R][r-(R-1)*blk];
return re;
}
inline ull ask(int l,int r)
{
int i,j,L=bel[l],R=bel[r];ull re=0;
for(i=L+1;i<R;++i) re+=sum[i];
j=min(L*blk,min(n,r));
for(i=l;i<=j;++i) re+=query(df[i],ot[i]);
if(L!=R){
j=(R-1)*blk;
for(i=r;i>j;--i) re+=query(df[i],ot[i]);
}
return re;
}
}
using namespace FK;
int main(){
freopen("quiz.in","r",stdin);
freopen("quiz.out","w",stdout);
int i,j,x,y,l,r;
rd(n);rd(m);
for(i=1;i<=n;++i) rd(val[i]);
for(i=1;i<=n;++i){
rd(x);rd(y);if(x>y) swap(x,y);
if(!x) rt=y;else {lk(x,y);lk(y,x);}
}
dfs(rt,0);
blk=(int)sqrt(n);cot=(n-1)/blk+1;
for(i=1;i<=n;++i) bel[i]=(i-1)/blk+1;
for(i=1;i<=cot;++i){
l=(i-1)*blk+1;r=min(n,i*blk);
for(j=l;j<=r;++j) c[df[j]]++,c[ot[j]+1]--;
for(j=1;j<=n;++j){c[j]+=c[j-1];f[rv[j]][i]=c[j];sum[i]+=(ll)c[j]*val[rv[j]];}
memset(c,0,(n+2)<<2);
}
for(i=1;i<=cot;++i){
l=(i-1)*blk+1;r=min(n,i*blk);x=r-l+1;
for(j=1;j<=x;++j) ss[i][j]=ss[i][j-1]+val[rv[l+j-1]];
ss[i][0]=ss[i-1][0]+ss[i][x];
}
for(;m;--m){
rd(x);rd(l);rd(r);
if(x==1) chg(l,r);
else{prit(ask(l,r));putchar('\n');}
}
fclose(stdin);fclose(stdout);
return 0;
}
racing
线段树分治+按秩合并的并查集
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=7e4+10;
int n,m,lnv[N<<1],dep[N],bin[30];
int st[19][N<<1],df[N],rv[N<<1],dfn;
int ans[N],cnt[N],q[N],cur;
int head[N],to[N<<1],nxt[N<<1],tot;
struct pr{
int u,v;
pr(int u_=0,int v_=0):u(u_),v(v_){};
}le[N];
char cp;
template<class T>inline void rd(T &x)
{
cp=getchar();x=0;int f=0;
for(;!isdigit(cp);cp=getchar()) if(cp=='-') f=1;
for(;isdigit(cp);cp=getchar()) x=x*10+(cp^48);
if(f) x=-x;
}
inline void prit(int x)
{if(x>9) prit(x/10);putchar('0'+(x%10));}
inline void lk(int u,int v)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
void dfs(int x,int fr)
{
int i,j;dep[x]=dep[fr]+1;
rv[++dfn]=x;st[0][dfn]=x;df[x]=dfn;
for(i=head[x];i;i=nxt[i]){
j=to[i];if(j==fr) continue;
dfs(j,x);rv[++dfn]=x;st[0][dfn]=x;
}
}
inline int LCA(int x,int y)
{
x=df[x];y=df[y];if(x>y) swap(x,y);
int bs=lnv[y-x+1],ix=st[bs][x],iy=st[bs][y-bin[bs]+1];
return (dep[ix]<dep[iy])?ix:iy;
}
inline int dist(int x,int y)
{return dep[x]+dep[y]-(dep[LCA(x,y)]<<1);}
struct bcj{
int fa,id,h,d[2];
inline void ini(int x){fa=id=d[0]=d[1]=x;}
}b[N],stk[N<<3];
inline int getfa(int x){return x==b[x].fa?x:getfa(b[x].fa);}
namespace SGT{
#define mid ((l+r)>>1)
#define lc k<<1
#define rc k<<1|1
#define lcc lc,l,mid
#define rcc rc,mid+1,r
int top;
vector<int>hv[N<<2];
void ins(int k,int l,int r,int L,int R,int id)
{
if(L>R) return;
if(L<=l && r<=R) {hv[k].pb(id);return;}
if(L<=mid) ins(lcc,L,R,id);
if(R>mid) ins(rcc,L,R,id);
}
inline void merge(int x,int y)
{
int i,j,k,s=dist(b[x].d[0],b[x].d[1]),ix=b[x].d[0],iy=b[x].d[1];
j=dist(b[y].d[0],b[y].d[1]);if(j>s) s=j,ix=b[y].d[0],iy=b[y].d[1];
for(i=0;i<2;++i)
for(j=0;j<2;++j){
k=dist(b[x].d[i],b[y].d[j]);
if(k>s) s=k,ix=b[x].d[i],iy=b[y].d[j];
}
if(b[x].h<b[y].h) swap(x,y);stk[++top]=b[x];stk[++top]=b[y];
b[x].h=max(b[x].h,b[y].h+1);b[y].fa=x;b[x].d[0]=ix;b[x].d[1]=iy;
cur=max(cur,s);
}
void sol(int k,int l,int r)
{
if(cnt[r]==cnt[l-1]) return;
int pos=top,ori=cur,i,j,x,y;
for(i=hv[k].size()-1;i>=0;--i){
j=hv[k][i];
x=getfa(le[j].u);y=getfa(le[j].v);
merge(x,y);
}
if(l!=r){sol(lcc);sol(rcc);}
else ans[l]=cur;
//reback
cur=ori;
for(;top>pos;--top) b[stk[top].id]=stk[top];
}
}
int main(){
freopen("racing.in","r",stdin);
freopen("racing.out","w",stdout);
int i,j,lim,x,y,l,r;
//init
rd(n);rd(m);
for(i=1;i<n;++i){
rd(x);rd(y);rd(l);rd(r);lk(x,y);lk(y,x);
le[i]=pr(x,y);l=max(l,1);r=min(r,n);
SGT::ins(1,1,n,l,r,i);
}
//precal LCA
dfs(1,0);
bin[0]=1;for(i=1;i<25;++i) bin[i]=bin[i-1]<<1;
for(i=2;i<=dfn;++i) lnv[i]=lnv[i>>1]+1;
for(i=1;bin[i]<=dfn;++i)
for(j=1;j+bin[i]-1<=dfn;++j){
x=st[i-1][j];y=st[i-1][j+bin[i-1]];
st[i][j]=(dep[x]<dep[y])?x:y;
}
//pre bcj
for(i=1;i<=n;++i) b[i].ini(i);
//solve
for(i=1;i<=m;++i){rd(q[i]);cnt[q[i]]++;}
for(i=2;i<=n;++i) cnt[i]+=cnt[i-1];
SGT::sol(1,1,n);
for(i=1;i<=m;++i){
prit(ans[q[i]]);if(i<m) putchar('\n');
}
fclose(stdin);fclose(stdout);
return 0;
}
总结
STO 差点AK的LPA (跪
T1没有看出来是斯坦纳树是真的蠢!(不过乱搞骗了70pts算是进步
T2分块套分块就不会了,需要复习一下DS的基本套路
T3不解释