当前位置:网站首页>P4775 [NOI2018] Intelligence Center (Line Segment Tree Merging)
P4775 [NOI2018] Intelligence Center (Line Segment Tree Merging)
2022-07-29 18:32:00 【wind__whisper】
前言
似乎也没有那么难?
But it also don't want to.
解析
For the two cross path ( u 1 , v 1 , c 1 ) , ( u 2 , v 2 , c 2 ) (u_1,v_1,c_1),(u_2,v_2,c_2) (u1,v1,c1),(u2,v2,c2),设 t = l c a ( u 1 , u 1 ) t=lca(u_1,u_1) t=lca(u1,u1) 为四个 lca 中最深的,So the cost of二倍可以写为 d i s ( u 1 , v 1 ) + d i s ( u 2 , v 2 ) + d i s ( u 1 , u 2 ) + d i s ( v 1 , v 2 ) − 2 c 1 − 2 c 2 dis(u_1,v_1)+dis(u_2,v_2)+dis(u_1,u_2)+dis(v_1,v_2)-2c_1-2c_2 dis(u1,v1)+dis(u2,v2)+dis(u1,u2)+dis(v1,v2)−2c1−2c2.
枚举 t t t 的位置,Distance can be written as d i s ( u 1 , v 1 ) + d e p u 1 − 2 c 1 + d i s ( u 2 , v 2 ) + d e p u 2 − 2 c 2 + d i s ( v 1 , v 2 ) − 2 d e p t dis(u_1,v_1)+dep_{u_1}-2c_1+dis(u_2,v_2)+dep_{u_2}-2c_2+dis(v_1,v_2)-2dep_t dis(u1,v1)+depu1−2c1+dis(u2,v2)+depu2−2c2+dis(v1,v2)−2dept,可以看成 d i s ( v 1 , v 2 ) + w 1 + w 2 − 2 d e p t dis(v_1,v_2)+w_1+w_2-2dep_t dis(v1,v2)+w1+w2−2dept 的形式.
See maximum distance,Easy to think of line segment tree maintenance of the diameter of the classical approach.
Can be seen as new“ v 1 v_1 v1” Is the original point out a length of w 1 w_1 w1 的边,So still can be depicted as a tree structure,Although there is a negative right side,But due to the negative right side there must be an endpoint is leaves,So the original conclusion or right.
Each node maintains subtree within“v”节点集合,Merge to update the answer,Line segment tree merge again can,时空复杂度 O ( m log m + n log n ) O(m\log m+n\log n) O(mlogm+nlogn).
Remember to arrive again lca The point before delete.
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("line: %d\n",__LINE__)
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)) {
if(c=='-')f=-1;c=getchar();}
while(isdigit(c)) {
x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
bool mem1;
const int N=2e5+100;
const ll inf=2e18;
const int mod=998244353;
const bool Flag=0;
#define add(x,y) ((((x)+=(y))>=mod)&&((x)-=mod))
inline ll ksm(ll x,ll k){
ll res(1);
while(k){
if(k&1) res=res*x%mod;
x=x*x%mod;
k>>=1;
}
return res;
}
int n,m;
struct edge{
int to,nxt,w;
}p[N<<1];
int fi[N],cnt;
inline void addline(int x,int y,int w){
p[++cnt]=(edge){
y,fi[x],w};fi[x]=cnt;
}
int q[N],dep[N],tim,pos[N];
ll dis[N];
int pl[N][20];
inline int jump(int x,int anc){
if(Flag) printf("jump: x=%d anc=%d\n",x,anc);
for(int k=16;k>=0;k--){
if(dep[pl[x][k]]<=dep[anc]) continue;
x=pl[x][k];
}
if(Flag) printf(" p=%d\n",x);
return x;
}
void dfs(int x,int f){
dep[x]=dep[f]+1;
pos[x]=++tim;
q[tim]=x;
pl[x][0]=f;
for(int k=1;pl[x][k-1];k++) pl[x][k]=pl[pl[x][k-1]][k-1];
for(int i=fi[x];~i;i=p[i].nxt){
int to=p[i].to;
if(to==f) continue;
dis[to]=dis[x]+p[i].w;
dfs(to,x);
q[++tim]=x;
}
return;
}
int mn[N][20],lg[N],mi[20];
inline int cmp(int x,int y){
return dep[x]<dep[y]?x:y;}
void ST(){
lg[0]=-1;
for(int i=1;i<=tim;i++) lg[i]=lg[i>>1]+1;
mi[0]=1;
for(int i=1;i<=lg[tim];i++) mi[i]=mi[i-1]<<1;
for(int i=1;i<=tim;i++) mn[i][0]=q[i];
for(int k=1;k<=lg[tim];k++){
for(int i=1;i+mi[k]-1<=tim;i++) mn[i][k]=cmp(mn[i][k-1],mn[i+mi[k-1]][k-1]);
}
return;
}
inline int Lca(int x,int y){
int l=pos[x],r=pos[y];
if(l>r) swap(l,r);
int k=lg[r-l+1];
//printf(" x=%d y=%d (%d %d) Lca=%d\n",x,y,pos[x],pos[y],cmp(mn[l][k],mn[r-mi[k]+1][k]));
return cmp(mn[l][k],mn[r-mi[k]+1][k]);
}
inline ll Dis(int x,int y){
return dis[x]+dis[y]-2*dis[Lca(x,y)];
}
struct pt{
int id;
ll w;
};
inline ll calc(const pt &a,const pt &b){
return Dis(a.id,b.id)+a.w+b.w;
}
int id[N],ed[N],rku[N],rkv[N];
struct node{
pt x,y;
};
inline void print(const node &a,int op=1){
printf("[ (%d %lld) (%d %lld) ] %c",a.x.id,a.x.w,a.y.id,a.y.w,op?'\n':' ');
}
inline ll getans(const node &a,const node &b){
ll q=calc(a.x,b.x),w=calc(a.x,b.y),e=calc(a.y,b.x),r=calc(a.y,b.y),mx=max({
q,w,e,r});
return mx;
}
inline node merge(const node &a,const node &b){
ll q=calc(a.x,b.x),w=calc(a.x,b.y),e=calc(a.y,b.x),r=calc(a.y,b.y),t=calc(a.x,a.y),y=calc(b.x,b.y),mx=max({
q,w,e,r,t,y});
if(mx==q) return (node){
a.x,b.x};
if(mx==w) return (node){
a.x,b.y};
if(mx==e) return (node){
a.y,b.x};
if(mx==r) return (node){
a.y,b.y};
if(mx==t) return (node){
a.x,a.y};
if(mx==y) return (node){
b.x,b.y};
assert(0);
}
struct tree{
int ls,rs;
node o;
}tr[N*30];
int rt[N],tot;
inline void pushup(int k){
tr[k].o=merge(tr[tr[k].ls].o,tr[tr[k].rs].o);
/*printf("merge: "); print(tr[tr[k].ls].o,0); print(tr[tr[k].rs].o,0); print(tr[k].o,1);*/
return;
}
#define mid ((l+r)>>1)
inline int New(){
tr[++tot]=tr[0];
return tot;
}
void upd(int &k,int l,int r,int p,ll w,int op){
if(!k) k=New();
if(l==r){
assert(id[l]);
if(op==1) tr[k].o.x=(pt){
id[l],w};
else tr[k].o.x=(pt){
id[l],-inf};
return;
}
if(p<=mid) upd(tr[k].ls,l,mid,p,w,op);
else upd(tr[k].rs,mid+1,r,p,w,op);
pushup(k);
return;
}
int merge(int x,int y){
if(!x||!y) return x|y;
int now=++tot;
tr[now].ls=merge(tr[x].ls,tr[y].ls);
tr[now].rs=merge(tr[x].rs,tr[y].rs);
pushup(now);
return now;
}
struct ope{
int op,p;
ll w;
};
vector<ope>ve[N];
int u[N],v[N];
ll c[N];
int S;
ll ans;
void solve(int x,int f){
for(int i=fi[x];~i;i=p[i].nxt){
int to=p[i].to;
if(to==f) continue;
solve(to,x);
}
if(Flag) printf("solve: x=%d\n",x);
for(ope o:ve[x]){
if(o.op==1){
pt ww=(pt){
id[o.p],o.w};
ans=max(ans,calc(ww,tr[rt[x]].o.x)-2*dis[x]);
ans=max(ans,calc(ww,tr[rt[x]].o.y)-2*dis[x]);
upd(rt[x],1,S,o.p,o.w,o.op);
if(Flag) printf(" ins: p=%d x=%d\n",o.p,id[o.p]);
}
}
for(int i=fi[x];~i;i=p[i].nxt){
int to=p[i].to;
if(to==f) continue;
ll o=getans(tr[rt[x]].o,tr[rt[to]].o)-2*dis[x];
if(Flag) if(o>ans){
printf("%d -> %d o=%lld ",x,to,o);
print(tr[rt[x]].o,0);
print(tr[rt[to]].o,1);
}
ans=max(ans,o);
rt[x]=merge(rt[x],rt[to]);
}
for(ope o:ve[x]){
if(o.op==-1){
upd(rt[x],1,S,o.p,o.w,o.op);
if(Flag) printf(" del: p=%d x=%d\n",o.p,id[o.p]);
}
}
return;
}
void init(){
tim=0;
cnt=-1;
tot=0;
ans=-inf;
tr[0].o.x=tr[0].o.y=(pt){
1,-inf};
for(int i=1;i<=n;i++){
fi[i]=-1;
memset(pl[i],0,sizeof(pl[i]));
ed[i]=0;
rt[i]=0;
ve[i].clear();
}
}
void work(){
n=read();
init();
for(int i=1;i<n;i++){
int x=read(),y=read(),w=read();
addline(x,y,w);
addline(y,x,w);
}
dfs(1,0);
ST();
m=read();
for(int i=1;i<=m;i++){
u[i]=read();v[i]=read();
c[i]=Dis(u[i],v[i])-read()*2;
rku[i]=++ed[u[i]];rkv[i]=++ed[v[i]];
}
for(int i=1;i<=n;i++){
ed[i]+=ed[i-1];
for(int j=ed[i-1]+1;j<=ed[i];j++) id[j]=i;
}
S=ed[n];
for(int i=1;i<=m;i++){
int anc=Lca(u[i],v[i]);
if(anc!=u[i]){
int p=jump(u[i],anc);
ve[u[i]].push_back((ope){
1,ed[v[i]-1]+rkv[i],c[i]+dis[u[i]]});
ve[p].push_back((ope){
-1,ed[v[i]-1]+rkv[i],c[i]+dis[u[i]]});
}
if(anc!=v[i]){
int p=jump(v[i],anc);
ve[v[i]].push_back((ope){
1,ed[u[i]-1]+rku[i],c[i]+dis[v[i]]});
ve[p].push_back((ope){
-1,ed[u[i]-1]+rku[i],c[i]+dis[v[i]]});
}
}
solve(1,0);
if(ans<-1e18) puts("F");
else printf("%lld\n",ans>>1);
}
bool mem2;
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
debug("mem=%.2lf\n",abs(&mem2-&mem1)/1024./1024);
int T=read();
while(T--){
//if(T%100==0) debug("%d\n",T);
work();
}
return 0;
}
边栏推荐
- [High Concurrency] I used multithreading to optimize the massive data proofreading system under the billion-level traffic e-commerce business, and the performance was directly improved by 200%!!(The w
- 宏定义小方法
- [High Concurrency] I used multithreading to further optimize the massive data proofreading system under the billion-level traffic e-commerce business, and the performance has been improved by 200% aga
- Pocket money
- 管理层换血,魏建军求变,长城能告别“命悬一线”吗?
- leetcode141 -- 环形链表
- 【运维】ssh tunneling 依靠ssh的22端口实现访问远程服务器的接口服务
- 硬核!世界顶级级架构师编写2580页DDD领域驱动设计笔记,也太强了!
- 【深度学习】YOLO转VOC VOC转YOLO
- 解析正则表达式的语法(二)
猜你喜欢

The Huazhong Agricultural University team proposes: a heterogeneous network-based method that can automatically extract meta-paths and predict drug-target interactions

不同的 DAO 对世界带来的改变

气数已尽!运营 23 年,昔日“国内第一大电商网站”黄了。。。

刚刚,60后复旦校友IPO敲钟:市值400亿

Live '| 37 mobile game analysis of how to implement user use StarRocks portrait

js选择多张图片对比功能插件

UNIX Environment Advanced Programming Chapter 3

service事物失效如何获取代理事物

lua-调试技巧

【英语考研词汇训练营】Day 17 —— espresso,ultimate,gradually,detect,dimension
随机推荐
【Mysql系列】02_连接+表
剑指offer专项突击版第14天
利用 JMeter 压测上传和下载接口实战
NFTScan and PANews jointly release multi-chain NFT data analysis report
如何让照片中的人物笑起来?HMS Core视频编辑服务一键微笑功能,让人物笑容更自然
不堆概念、换个角度聊多线程并发编程
传统渲染农场和云渲染农场选择哪个好?
回帖免责声明-转载
详解析构函数、拷贝构造函数
解决报错Unsupported field: HourOfDay
UNIX Environment Advanced Programming Chapter 3
SSM整合案例分析(详解)
赠书|《软硬件融合》带你学习从CPU、DSP到软硬件融合的计算创新之路
译文推荐 | 调试 BookKeeper 协议 - 无界 Ledger
How CRM Helps Enterprise Marketing Acquire Customers
浅谈智能家居应用及传输方式
The 14th day of the special assault version of the sword offer
蓝色社交图标登录页面
service事物失效如何获取代理事物
手动SET返回PageInfo对象