P1505 [国家集训队]旅游
大裸题,第一次少打了个min。。。
错了无数次。。。
才发现少了个min
。。。。,也可以LCT
#include<cstdio>
#include<iostream>
#include<set>
using namespace std;
const int M=200010,INF=1000;
int n,m,to[2*M],nex[M*2],head[M],vis[M],flag[M],coss[M],cap[M],caps[M],tot=1,val[M],f[M],cos[M*2],dep[M],top[M],cnt,size[M],ans,son[M],id[M];
struct xianduantree{
int sum[4*M],minn[4*M],maxn[4*M],flag[4*M];
void update(int x){
sum[x]=(sum[x<<1]+sum[x<<1|1]);
minn[x]=min(minn[x<<1],minn[x<<1|1]);
maxn[x]=max(maxn[x<<1],maxn[x<<1|1]);
}
void built(int o,int l,int r){
if(l==r) sum[o]=val[l],minn[o]=val[l],maxn[o]=val[l];
else {
int mid=(l+r)>>1;
built(o<<1,l,mid);
built(o<<1|1,mid+1,r);
update(o);
}
}
void pushdown(int o){
if(flag[o]==1) return ;
flag[o<<1]*=-1;flag[o<<1|1]*=-1;
maxn[o<<1]*=-1;maxn[o<<1|1]*=-1;
minn[o<<1]*=-1;minn[o<<1|1]*=-1;
sum[o<<1|1]*=-1;sum[o<<1]*=-1;
swap(minn[o<<1],maxn[o<<1]);
swap(maxn[o<<1|1],minn[o<<1|1]);
flag[o]=1;
}
void modify_1(int o,int l,int r,int id,int ins){
if(l==r) {
minn[o]=ins;maxn[o]=ins;
sum[o]=ins;return ;
}
int mid=(l+r)>>1;
pushdown(o);
if(id<=mid)modify_1(o<<1,l,mid,id,ins);
else modify_1(o<<1|1,mid+1,r,id,ins);
update(o);
}
void modify_2(int o,int l,int r,int ql,int qr){
if(l>qr||r<ql) return ;
if(l>=ql&&r<=qr) {
flag[o]*=-1;minn[o]*=-1;
sum[o]*=-1;maxn[o]*=-1;swap(minn[o],maxn[o]);
return ;
}
int mid=(l+r)>>1;
pushdown(o);
modify_2(o<<1,l,mid,ql,qr);
modify_2(o<<1|1,mid+1,r,ql,qr);
update(o);
}
int query_sum(int o,int l,int r,int ql,int qr){
if(l>qr||r<ql) return 0;
if(l>=ql&&r<=qr) return sum[o];
int mid=(l+r)>>1;
pushdown(o);
return (query_sum(o<<1,l,mid,ql,qr)+query_sum(o<<1|1,mid+1,r,ql,qr));
}
int query_min(int o,int l,int r,int ql,int qr){
if(l>qr||r<ql) return INF;
if(l>=ql&&r<=qr) return minn[o];
int mid=(l+r)>>1;
pushdown(o);
return min(query_min(o<<1,l,mid,ql,qr),query_min(o<<1|1,mid+1,r,ql,qr));
}
int query_max(int o,int l,int r,int ql,int qr){
if(l>qr||r<ql) return -INF;
if(l>=ql&&r<=qr) return maxn[o];
int mid=(l+r)>>1;
pushdown(o);
return max(query_max(o<<1,l,mid,ql,qr),query_max(o<<1|1,mid+1,r,ql,qr));
}
}T;
void add(int x,int y,int z){
nex[++tot]=head[x];cos[tot]=z;
to[tot]=y;head[x]=tot;
}
int dfs1(int x){
size[x]=1;dep[x]=dep[f[x]]+1;
int maxsi=0;
for(int i=head[x];i;i=nex[i]){
int tmp=to[i];
if(tmp!=f[x]){f[tmp]=x;
int siz=dfs1(tmp);
size[x]+=siz;
if(maxsi<siz)
son[x]=tmp,caps[x]=i/2,coss[x]=cos[i],maxsi=siz;
}
}
return size[x];
}
void dfs2(int x,int topx,int z,int ww){
top[x]=topx;
id[x]=++cnt;cap[ww]=x;
val[cnt]=z;
if(!son[x]){return ;}
dfs2(son[x],topx,coss[x],caps[x]);
for(int i=head[x],tmp;i;i=nex[i])
if(!id[tmp=to[i]])
dfs2(tmp,tmp,cos[i],i/2);
}
void add_x(int x,int y){
if(x==y) return ;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
T.modify_2(1,1,cnt,id[top[x]],id[x]);
x=f[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
T.modify_2(1,1,cnt,id[y]+1,id[x]);
}
int sum_x(int x,int y){
if(x==y) return 0;
int ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=(ans+T.query_sum(1,1,cnt,id[top[x]],id[x]));
x=f[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
ans=(ans+T.query_sum(1,1,cnt,id[y]+1,id[x]));
return ans;
}
int min_x(int x,int y){
if(x==y) return 0;
int ans=INF;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=min(ans,T.query_min(1,1,cnt,id[top[x]],id[x]));
x=f[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
ans=min(ans,T.query_min(1,1,cnt,id[y]+1,id[x]));
return ans;
}
int max_x(int x,int y){
if(x==y) return 0;
int ans=-INF;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=max(ans,T.query_max(1,1,cnt,id[top[x]],id[x]));
x=f[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
ans=max(ans,T.query_max(1,1,cnt,id[y]+1,id[x]));
return ans;
}
int main(){scanf("%d",&n);
for(int i=1;i<4*M;i++) T.flag[i]=1;
for(int i=1,x,y,z;i<n;i++) scanf("%d%d%d",&x,&y,&z),x++,y++,add(x,y,z),add(y,x,z);
dfs1(1);dfs2(1,1,0,n);T.built(1,1,cnt);T.minn[1]=INF,T.maxn[1]=-INF,T.sum[1]=0;
scanf("%d",&m);
while(m--){char s[20];int u,v;
cin>>s;
scanf("%d%d",&u,&v);u++,v++;
if(s[0]=='S') printf("%d\n",sum_x(u,v));
if(s[1]=='I') printf("%d\n",min_x(u,v));
if(s[1]=='A') printf("%d\n",max_x(u,v));
if(s[0]=='N') add_x(u,v);
if(s[0]=='C') u--,v--,T.modify_1(1,1,cnt,id[cap[u]],v);
}
}
[SDOI2015]寻宝游戏
树剖,用平衡树维护那个点有宝藏
然后找前驱和后继
发现删加边就是多了个与前驱后继的护理,如果正好在前驱后继的路上就不加
#include<cstdio>
#include<iostream>
#include<set>
#define int long long
using namespace std;
const int M=410000;
int n,m,to[2*M],nex[M*2],head[M],vis[M],flag[M],pos[M],tot,f[M],cos[M],dep[M],top[M],cnt,size[M],ans,son[M],id[M],low[M],dis[M],LCA,LCA2;
void add(int x,int y,int z){
nex[++tot]=head[x];cos[tot]=z;
to[tot]=y;head[x]=tot;
}
int dfs1(int x){
size[x]=1;dep[x]=dep[f[x]]+1;
int maxsi=0;
for(int i=head[x];i;i=nex[i]){
int tmp=to[i];
if(tmp!=f[x]){
f[tmp]=x;dis[tmp]=dis[x]+cos[i];
int siz=dfs1(tmp);
size[x]+=siz;
if(maxsi<siz)
son[x]=tmp,maxsi=siz;
}
}
return size[x];
}
void dfs2(int x,int topx){
top[x]=topx;
id[x]=++cnt;pos[cnt]=x;
if(!son[x]){low[x]=cnt;return ;}
dfs2(son[x],topx);
for(int i=head[x],tmp;i;i=nex[i])
if(!id[tmp=to[i]])
dfs2(tmp,tmp);
low[x]=cnt;
}
int lca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=f[top[x]];
}
return dep[x]>dep[y]?y:x;
}
set<int> s;
int dist(int x,int y){
return dis[x]+dis[y]-2*dis[lca(x,y)];
}
int left(int x){
if(s.empty())return x;
set<int>::iterator it=s.lower_bound(id[x]);
if(it==s.begin()) return pos[*(--s.end())];
else return pos[*(--it)];
}
int right(int x){
if(s.empty())return x;
set<int>::iterator it=s.upper_bound(id[x]);
if(it==s.end()) return pos[*s.begin()];
else return pos[*it];
}
int main(){scanf("%lld%lld",&n,&m);
for(int i=1,x,y,z;i<n;i++) scanf("%lld%lld%lld",&x,&y,&z),add(x,y,z),add(y,x,z);
dfs1(1);dfs2(1,1);
while(m--){int x,l,r;
scanf("%lld",&x);
if(flag[x]){
s.erase(id[x]);
l=right(x),r=left(x);
ans-=dist(x,l)+dist(r,x)-dist(l,r);
} else {
s.insert(id[x]);
l=right(x),r=left(x);
ans+=dist(x,l)+dist(r,x)-dist(l,r);
}
flag[x]^=1;
printf("%lld\n",ans);
}
}
P4069 [SDOI2016]游戏
树链剖分
用线段树维护
维护链头的值base,发现下面的值就是dist*k+base,找最大值用李超线段树维护这个一次函数
话说李超线段树还是不好打。。。
// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
const int M=1210000;const ll INF=123456789123456789;
int n,m,to[2*M],nex[M*2],head[M],tot,f[M],dep[M],top[M],val[M],cnt,size[M],son[M],rank[M],id[M];
ll dis[M],cos[2*M];
struct node{
ll k,b;int s;
node(ll K=0,ll B=0,int S=0){k=K;b=B;s=S;}
ll dist(int x){
return (dis[x]-dis[s])*k+b;
}
};
struct xianduantree{
node val[M*4];ll minn[M];
void build(int o,int l,int r){
val[o]=(node){0,INF,0};
minn[o]=INF;
if(l>=r) return;
int mid=(l+r)>>1;
build((o<<1),l,mid),build((o<<1)|1,mid+1,r);
}
void insert(int o,int l,int r,node ins){
ll ans=min(ins.dist(rank[l]),ins.dist(rank[r]));
node tmp=val[o];
if(l==r){
if(ans<val[o].dist(rank[l])) val[o]=ins;minn[o]=min(minn[o],ans);return ;
}int mid=(l+r)>>1;ans=min(ans,minn[o]);
if(ins.k>tmp.k) swap(ins,tmp);
if (ins.dist(rank[mid])<tmp.dist(rank[mid])){
val[o]=ins,minn[o]=min(minn[o],ans);
insert(o<<1,l,mid,tmp);
}
else{
val[o]=tmp,minn[o]=min(minn[o],ans);
insert(o<<1|1,mid+1,r,ins);
}
}
void change(int o,int l,int r,int ql,int qr,node ins){
if(l>=ql&&r<=qr) {
insert(o,l,r,ins);return ;
}
int mid=(l+r)>>1;
if(ql<=mid)change(o<<1,l,mid,ql,qr,ins);
if(qr>mid) change(o<<1|1,mid+1,r,ql,qr,ins);
minn[o]=min(minn[o],min(minn[o<<1],minn[o<<1|1]));
}
ll ask(int o,int l,int r,int ql,int qr){
int askl=max(ql,l),askr=min(r,qr);
ll ans=min(val[o].dist(rank[askl]),val[o].dist(rank[askr]));
if(ql<=l&&r<=qr) return min(ans,minn[o]);
int mid=(l+r)>>1;
if (ql<=mid) ans=min(ans,ask(o<<1,l,mid,ql,qr));
if (qr>mid) ans=min(ans,ask(o<<1|1,mid+1,r,ql,qr));
return ans;
}
}T;
void add(int x,int y,ll z){
to[++tot]=y;
nex[tot]=head[x];
cos[tot]=z;head[x]=tot;
}
int dfs1(int x){
size[x]=1;dep[x]=dep[f[x]]+1;
int maxsi=0;
for(int i=head[x];i;i=nex[i]){
int tmp=to[i];
if(tmp!=f[x]){
f[tmp]=x;dis[tmp]=dis[x]+cos[i];
int siz=dfs1(tmp);
size[x]+=siz;
if(maxsi<siz)
son[x]=tmp,maxsi=siz;
}
}
return size[x];
}
void dfs2(int x,int topx){
top[x]=topx;
id[x]=++cnt;rank[cnt]=x;
if(!son[x])return ;
dfs2(son[x],topx);
for(int i=head[x],tmp;i;i=nex[i])
if(!id[tmp=to[i]])
dfs2(tmp,tmp);
}
int lca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=f[top[x]];
}
return dep[x]>dep[y]?y:x;
}
void add_x(int x,int y,int a,int b){
int LCA=lca(x,y),s=x,opt=1;ll base;node ins;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y),opt^=1;
base=dis[top[x]]+dis[s]-2*dis[LCA];
if(opt==1) base=dis[s]-dis[top[x]];
base=a*base+b;
ins=node(opt?-a:a,base,top[x]);
T.change(1,1,cnt,id[top[x]],id[x],ins);
x=f[top[x]];
}
if(dep[x]<dep[y])swap(x,y),opt^=1;
base=dis[x]+dis[s]-2*dis[LCA];
if(opt==1) base=dis[s]-dis[x];
base=a*base+b;
ins=node(opt?-a:a,base,x);
T.change(1,1,cnt,id[y],id[x],ins);
}
ll min_x(int x,int y){
ll ans=INF;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=min(ans,T.ask(1,1,cnt,id[top[x]],id[x]));
x=f[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
ans=min(ans,T.ask(1,1,cnt,id[y],id[x]));
return ans;
}
int main(){
scanf("%d%d",&n,&m);ll w;
for(int i=1,x,y;i<n;i++) scanf("%d%d%lld",&x,&y,&w),add(x,y,w),add(y,x,w) ;
dfs1(1);dfs2(1,1);
T.build(1,1,cnt);
while(m--){
int opt,s,t,a,b;
scanf("%d%d%d",&opt,&s,&t);
if(opt==1) {
scanf("%d%d",&a,&b);
add_x(s,t,a,b);
}
if(opt==2) printf("%lld\n",min_x(s,t));
}
}