P1505 [国家集训队]旅游 树链剖分
生活随笔
收集整理的這篇文章主要介紹了
P1505 [国家集训队]旅游 树链剖分
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接
題意:樹上更新某一點權值,更新兩點簡單路徑權值,查詢最大,最小,和
思路:思路應該比較簡單,就是樹鏈剖分后用線段樹維護區間最大最小以及區間和。
但是本題比較特殊的是給的邊權,轉化為點權即可。但是查詢或者更新兩點x,y之間路徑的時候,x,y的lca點的點權對應的邊是
fathar[lca]--->lca這條邊,不屬于x->y的簡單路徑。
所以在更新或者查詢的時候,當處理到x,y屬于同一條鏈的時候
這個過程說的是查詢x->y,x,y一直往上跳,直到有一個跳到lca時(若dep[x]<dep[y],x就是lca)
這時x,y屬于一個連續區間,又因x點的權值不算,就是更新(dfn[x]+1,y),dfn為時間戳
所以算是一道比較基礎的樹鏈剖分吧。
但是,這該死的碼量,也太惡心了,我就寫了一個bug,找了整兩個小時?,wc
一個update1寫成update我就真找不到。。。我太難了
?
//#pragma comment (linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#include<list>
#include<time.h>
#define myself i,l,r
#define lson i<<1
#define rson i<<1|1
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define lowbit(x) x&(-x)
#define min4(a, b, c, d) min(min(a,b),min(c,d))
#define min3(x, y, z) min(min(x,y),z)
#define max3(x, y, z) max(max(x,y),z)
#define max4(a, b, c, d) max(max(a,b),max(c,d))
#define pii make_pair
#define pr pair<int,int>
//freopen("E://1.in","r",stdin);
//freopen("E://1.out","w",stdout);
typedef unsigned long long ull;
typedef long long ll;
const int inff = 0x3f3f3f3f;
const long long inFF = 9223372036854775807;
const int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
const int mdir[8][2] = {0, 1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 1, -1, -1, -1};
const double eps = 1e-10;
const double PI = acos(-1.0);
const double E = 2.718281828459;
using namespace std;
//const int mod=1e9+7;
const int maxn=2e5+5;
int d[maxn],f[maxn],dfn[maxn],tim[maxn],top[maxn],size[maxn],son[maxn],a[maxn];
int head[maxn],sign;
char s[3];
struct node
{int to,p,val;
}edge[maxn<<1];
struct nod
{int mx,mi,sum;
}tree[maxn<<2];
int lazy[maxn<<2];
int n,t;
void init()
{for(int i=0;i<=n;i++) head[i]=-1;sign=t=0;
}
void add(int u,int v,int val)
{edge[sign]=node{v,head[u],val};head[u]=sign++;
}
void dfs1(int u,int pre,int step)
{d[u]=step;f[u]=pre;size[u]=1;for(int i=head[u];~i;i=edge[i].p){int v=edge[i].to;if(v==pre) continue;a[v]=edge[i].val;dfs1(v,u,step+1);size[u]+=size[v];if(size[v]>size[son[u]]) son[u]=v;}
}
void dfs2(int u,int tp)
{dfn[u]=++t;tim[t]=u;top[u]=tp;if(son[u]) dfs2(son[u],tp);for(int i=head[u];~i;i=edge[i].p){int v=edge[i].to;if(v!=f[u]&&v!=son[u]) dfs2(v,v);}
}
void pushup(int i,int l,int r)
{tree[i].sum=tree[lson].sum+tree[rson].sum;tree[i].mx=max(tree[lson].mx,tree[rson].mx);tree[i].mi=min(tree[lson].mi,tree[rson].mi);
}
void pushdown(int i,int l,int r)
{if(lazy[i]){tree[lson].sum=-tree[lson].sum;tree[rson].sum=-tree[rson].sum;int t1=tree[lson].mx,t2=tree[rson].mx,s1=tree[lson].mi,s2=tree[rson].mi;tree[lson].mx=-s1,tree[rson].mx=-s2,tree[lson].mi=-t1,tree[rson].mi=-t2;lazy[lson]^=1;lazy[rson]^=1;lazy[i]=0;}
}
void build(int i,int l,int r)
{if(l==r){tree[i].sum=tree[i].mi=tree[i].mx=a[tim[l]];return ;}int mid=half;build(Lson);build(Rson);pushup(myself);
}
void update(int i,int l,int r,int x,int val)//單點更新
{if(l==r){tree[i].sum=tree[i].mi=tree[i].mx=val;return;}int mid=half;pushdown(myself);if(x<=mid) update(Lson,x,val);else update(Rson,x,val);pushup(myself);
}
void update1(int i,int l,int r,int ql,int qr)//區間取反
{if(ql>qr) return;if(ql<=l&&qr>=r){tree[i].sum=-tree[i].sum;lazy[i]=1-lazy[i];int x=tree[i].mi;tree[i].mi=-tree[i].mx;tree[i].mx=-x;return;}pushdown(myself);int mid=half;if(qr<=mid) update1(Lson,ql,qr);else if(ql>mid) update1(Rson,ql,qr);else update1(Lson,ql,mid),update1(Rson,mid+1,qr);pushup(myself);
}int find_sum(int i,int l,int r,int ql,int qr)
{if(ql>qr) return 0;if(ql<=l&&qr>=r) return tree[i].sum;pushdown(myself);int mid=half;if(qr<=mid) return find_sum(Lson,ql,qr);else if(ql>mid) return find_sum(Rson,ql,qr);else return find_sum(Lson,ql,mid)+find_sum(Rson,mid+1,qr);
}
int find_max(int i,int l,int r,int ql,int qr)
{if(ql>qr) return -inff;if(ql<=l&&qr>=r) return tree[i].mx;pushdown(myself);int mid=half;if(qr<=mid) return find_max(Lson,ql,qr);else if(ql>mid) return find_max(Rson,ql,qr);else return max(find_max(Lson,ql,mid),find_max(Rson,mid+1,qr));
}
int find_min(int i,int l,int r,int ql,int qr)
{if(ql>qr) return inff;if(ql<=l&&qr>=r) return tree[i].mi;pushdown(myself);int mid=half;if(qr<=mid) return find_min(Lson,ql,qr);else if(ql>mid) return find_min(Rson,ql,qr);else return min(find_min(Lson,ql,mid),find_min(Rson,mid+1,qr));
}
void solve(int x,int y)//區間更新pre處理
{while(top[x]!=top[y]){if(d[top[x]]<d[top[y]]) swap(x,y);update1(1,1,n,dfn[top[x]],dfn[x]);x=f[top[x]];}if(d[x]>d[y]) swap(x,y);update1(1,1,t,dfn[x]+1,dfn[y]);
}
int get_max(int x,int y)
{int ans=-inff;while(top[x]!=top[y]){if(d[top[x]]<d[top[y]]) swap(x,y);ans=max(ans,find_max(1,1,t,dfn[top[x]],dfn[x]));x=f[top[x]];}if(d[x]>d[y]) swap(x,y);ans=max(ans,find_max(1,1,t,dfn[x]+1,dfn[y]));return ans;}
int get_min(int x,int y)
{int ans=inff;while(top[x]!=top[y]){if(d[top[x]]<d[top[y]]) swap(x,y);ans=min(ans,find_min(1,1,t,dfn[top[x]],dfn[x]));x=f[top[x]];}if(d[x]>d[y]) swap(x,y);ans=min(ans,find_min(1,1,t,dfn[x]+1,dfn[y]));return ans;
}
int get_sum(int x,int y)
{int ans=0;while(top[x]!=top[y]){if(d[top[x]]<d[top[y]]) swap(x,y);ans+=find_sum(1,1,t,dfn[top[x]],dfn[x]);x=f[top[x]];}if(d[x]>d[y]) swap(x,y);ans+=find_sum(1,1,t,dfn[x]+1,dfn[y]);return ans;
}
int main()
{
// freopen("E://2.in","r",stdin);
// freopen("E://1.out","w",stdout);cin>>n;int x,y,val;init();for(int i=1;i<n;i++){scanf("%d %d %d",&x,&y,&val);x++,y++;add(x,y,val),add(y,x,val);}dfs1(1,1,1);dfs2(1,1);build(1,1,n);int r;cin>>r;while(r--){scanf("%s",s);scanf("%d %d",&x,&y);x++,y++;if(s[0]=='C') update(1,1,n,dfn[x],y-1);else if(s[0]=='N') solve(x,y);else if(s[2]=='M') printf("%d\n",get_sum(x,y));else if(s[2]=='X') printf("%d\n",get_max(x,y));else printf("%d\n",get_min(x,y));}return 0;
}
?
總結
以上是生活随笔為你收集整理的P1505 [国家集训队]旅游 树链剖分的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【模板】树链剖分 P3384
- 下一篇: 差分约束-图论