一开始感觉时间复杂度不够,后来还是冲了,发现很快
感觉自己卡常不行,要多练
巨大恶心题!写了我两个小时,心态差点崩了,还好调出来了
但出题人是 s b sb sb,卡常卡成暴力分了 ( 55 p t s ) (55pts) (55pts) T_T
比赛链接
s b sb sb 题,枚举公约数然后二分即可,时间复杂度 O ( n l o g n l o g V ) O(nlognlogV) O(nlognlogV),因为是 g c d gcd gcd,所以 l o g V logV logV 远远跑不满
巨大恶心卡常题,不过只卡了 10 p t s 10pts 10pts
正解好像是倍增答案
但有人矩乘然后循环展开过了,感觉很神奇
看到路径,不难想到点分治
然后就用线段树维护即可, 不难想但很难写
还被卡常了,现在才发现我的点分治板子是有多慢(卡常 + 改了 w x q wxq wxq 的点分治板子就过了)
时间复杂度 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)
#include
using namespace std;
const int N=100100,inf=2e9;
typedef pair<int,int> pii;
int n,m,ans=-inf,tot,mnms;
int L[N],R[N],idx;
int val1[N],val2[N];
bool TTT[N],cov[N],vis[N];
vector<int> G[N];
vector<pii> key[N],revkey[N];
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
struct SegmentTree{
int seg[N*3],tag[N*3];
void clear(int tot){ for(int i=1;i<=tot*3;i++) seg[i]=-inf,tag[i]=0;}
void down(int x,int val){ seg[x]+=val,tag[x]+=val;}
void pushdown(int x){
down(x<<1,tag[x]),down(x<<1^1,tag[x]);
tag[x]=0;
}
void modify(int l,int r,int x,int L,int R,int val,int type){
if(L<=l&&r<=R){
if(type) down(x,val);
else seg[x]=val;
return;
}
pushdown(x);
int mid=(l+r)>>1;
if(mid>=L) modify(l,mid,x<<1,L,R,val,type);
if(mid<R) modify(mid+1,r,x<<1^1,L,R,val,type);
seg[x]=max(seg[x<<1],seg[x<<1^1]);
}
}sg;
int siz[N];
void get_size_wxq(int u,int fa){
siz[u]=1;
for(int v:G[u]) if(!vis[v]&&v!=fa) get_size_wxq(v,u),siz[u]+=siz[v];
}
int get_root_wxq(int u,int fa,int &rt){
int siz=1,ms=0;
for(int v:G[u]) if(!vis[v]&&v!=fa){
int t=get_root_wxq(v,u,rt);
siz+=t,ms=max(ms,t);
}
ms=max(ms,tot-siz);
if(ms<mnms) mnms=ms,rt=u;
return siz;
}
void init(int u,int fa){
L[u]=++idx,cov[u]=1,val1[u]=val2[u]=0;
for(int v:G[u]) if(v!=fa&&!vis[v]) init(v,u);
R[u]=idx;
}
void clcov_wxq(int u,int fa){
cov[u]=0;
for(int v:G[u]) if(v!=fa&&!vis[v]) clcov_wxq(v,u);
}
void wxq12(int u,int fa){
TTT[u]=1;
for(pii ke:key[u]) if(TTT[ke.first]) val1[u]+=ke.second;
for(pii ke:revkey[u]) if(TTT[ke.first]) val2[u]+=ke.second;
for(int v:G[u]) if(v!=fa&&!vis[v]) val1[v]+=val1[u],val2[v]+=val2[u],wxq12(v,u);
TTT[u]=0;
}
void add_wxq(int u,int Lb,int Rb,int val){
for(pii ke:key[u]){
int x=ke.first,w=ke.second;
if(!cov[x]) continue;
if(L[x]>1&&Lb<=L[x]&&R[x]<=Rb) sg.modify(1,idx,1,L[x],R[x],w*val,1);
}
}
void wxq(int u,int fa,int Lb,int Rb,int rt){
add_wxq(u,Lb,Rb,1);
if(Lb<=Rb) ans=max(ans,val1[u]+sg.seg[1]-val1[rt]);
for(int v:G[u]) if(v!=fa&&!vis[v]) wxq(v,u,Lb,Rb,rt);
add_wxq(u,Lb,Rb,-1);
}
void insert_wxq(int u,int fa){
sg.modify(1,idx,1,L[u],L[u],val2[u],0);
for(int v:G[u]) if(v!=fa&&!vis[v]) insert_wxq(v,u);
}
void wxq_solve(int rt){
get_size_wxq(rt,-1),mnms=inf,tot=siz[rt];
// get_root_wxq(rt,-1,rt);
while(true){
bool fl=0;
for(auto v:G[rt])if(siz[v]<siz[rt]&&siz[v]*2>=tot){
fl=1,rt=v;
break;
}
if(!fl)break;
}
vis[rt]=1;
idx=0,init(rt,-1);
wxq12(rt,-1);
ans=max(ans,val1[rt]);
sg.clear(idx);sg.modify(1,idx,1,1,1,val2[rt],0);
for(int v:G[rt]){
if(vis[v]) continue;
wxq(v,rt,1,L[v]-1,rt),insert_wxq(v,rt);
}
sg.clear(idx);
for(int i=G[rt].size()-1;i>=0;i--){
int v=G[rt][i];
if(vis[v]) continue;
wxq(v,rt,R[v]+1,idx,rt),insert_wxq(v,rt);
}
ans=max(ans,sg.seg[1]);
clcov_wxq(rt,-1);
for(int v:G[rt]) if(!vis[v]) wxq_solve(v);
}
int main(){
freopen("score.in","r",stdin);
freopen("score.out","w",stdout);
n=read(),m=read();
for(int i=1;i<n;i++){
int x=read(),y=read();
G[x].emplace_back(y),G[y].emplace_back(x);
}
for(int i=1,x,y,w;i<=m;i++){
x=read(),y=read(),w=read();
key[y].emplace_back(make_pair(x,w));
revkey[x].emplace_back(make_pair(y,w));
}
wxq_solve(1);
printf("%d\n",ans);
return 0;
}
// orz wxq
不会,是道动态 m s t mst mst 板子题