BZOJ3531-[Sdoi2014]旅行
題解:
正常的樹鏈剖分,但由於顏色的限制,不能只開一棵線段樹,我們可以對每個顏色都開一棵線段樹,但這樣空間不行,我們只要建實時開點線段樹,就可以了。
對於詢問,只要在那個顏色的線段樹上詢問就好了。
#include<iostream>
#include<cstdio>
#include<cstring>
#define M 10000005
#define N 100005
using namespace std;
int n,m,cnt,place,size;
int s[17],w[N],c[N],root[N],fa[N][17],deep[N],vis[N];
int pl[N],belong[N],son[N],head[N],ls[M],rs[M],mx[M],sum[M];
struct data
{
int vet,next;
}edge[N*2];
void ins(int u,int v)
{
edge[++cnt].vet=v;
edge[cnt].next=head[u];
head[u]=cnt;
}
void dfs1(int x)
{
vis[x]=1;son[x]=1;
for(int i=1;i<=16;i++)
if(s[i]<=deep[x])fa[x ][i]=fa[fa[x][i-1]][i-1];
else break;
for(int i=head[x];i;i=edge[i].next)
{
int v=edge[i].vet;
if(vis[v])continue;
deep[v]=deep[x]+1;
fa[v][0]=x;
dfs1(v);
son[x]+=son[v];
}
}
void dfs2(int x,int chain)
{
place++;
pl[x]=place;
belong[x ]=chain;
int k=0;
for(int i=head[x];i;i=edge[i].next)
{
int v=edge[i].vet;
if(deep[v]>deep[x]&&son[v]>son[k])
k=v;
}
if(k)dfs2(k,chain);
for(int i=head[x];i;i=edge[i].next)
{
int v=edge[i].vet;
if(deep[v]>deep[x]&&v!=k)
dfs2(v,v);
}
}
int lca(int x,int y)
{
if(deep[x]<deep[y])swap(x,y);
int t=deep[x]-deep[y];
for(int i=0;i<=16;i++)
if(s[i]&t)x=fa[x][i];
for(int i=16;i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
if(x==y)return x;
return fa[x][0];
}
void change(int &k,int l,int r,int x,int num)
{
if(!k)k=++size;
if(l==r)
{
mx[k]=sum[k]=num;
return;
}
int mid=(l+r)>>1;
if(x<=mid)change(ls[k],l,mid,x,num);else
change(rs[k],mid+1,r,x,num);
mx[k]=max(mx[ls[k]],mx[rs[k]]);
sum[k]=sum[ls[k]]+sum[rs[k]];
}
int askmx(int k,int l,int r,int x,int y)
{
if(!k)return 0;
if(l==x&&y==r)return mx[k];
int mid=(l+r)>>1;
if(y<=mid)return askmx(ls[k],l,mid,x,y);else
if(x>mid)return askmx(rs[k],mid+1,r,x,y);else
return max(askmx(ls[k],l,mid,x,mid),askmx(rs[k],mid+1,r,mid+1,y));
}
int asksum(int k,int l,int r,int x,int y)
{
if(!k)return 0;
if(l==x&&y==r)return sum[k];
int mid=(l+r)>>1;
if(y<=mid)return asksum(ls[k],l,mid,x,y);else
if(x>mid)return asksum(rs[k],mid+1,r,x,y);else
return asksum(ls[k],l,mid,x,mid)+asksum(rs[k],mid+1,r,mid+1,y);
}
int solvemx(int c,int x,int f)
{
int mx=0;
while(belong[x]!=belong[f])
{
mx=max(mx,askmx(root[c],1,n,pl[belong[x]],pl[x]));
x=fa[belong[x]][0];
}
mx=max(mx,askmx(root[c],1,n,pl[f],pl[x]));
return mx;
}
int solvesum(int c,int x,int f)
{
int sum=0;
while(belong[x]!=belong[f])
{
sum+=asksum(root[c],1,n,pl[belong[x]],pl[x]);
x=fa[belong[x]][0];
}
sum+=asksum(root[c],1,n,pl[f],pl[x]);
return sum;
}
int main()
{
s[0]=1;
for(int i=1;i<=16;i++)
s[i]=(s[i-1]<<1);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d%d",&w[i],&c[i]);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
ins(u,v);
}
dfs1(1);dfs2(1,1);
for(int i=1;i<=n;i++)
change(root[c[i]],1,n,pl[i],w[i]);
for(int i=1;i<=m;i++)
{
char ch[5];scanf("%s",ch);
int x,y;
scanf("%d%d",&x,&y);
if(ch[0]=='C')
{
if(ch[1]=='C')
{
change(root[c[x]],1,n,pl[x],0);
c[x]=y;
change(root[c[x]],1,n,pl[x],w[x]);
}else
{
change(root[c[x]],1,n,pl[x],y);
w[x]=y;
}
}else
{
int f=lca(x,y);
if(ch[1]=='S')
{
int t=solvesum(c[x],x,f)+solvesum(c[x],y,f);
if(c[x]==c[f])t-=w[f];
printf("%d\n",t);
}else
printf("%d\n",max(solvemx(c[x],x,f),solvemx(c[x],y,f)));
}
}
return 0;
}
相關推薦
bzoj3531[Sdoi2014]旅行
輸入 mes for gpo 路徑 left long long bzoj3 不變 3531: [Sdoi2014]旅行Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 2640 Solved: 1142[Submit][St
BZOJ3531-[Sdoi2014]旅行
題解: 正常的樹鏈剖分,但由於顏色的限制,不能只開一棵線段樹,我們可以對每個顏色都開一棵線段樹,但這樣空間不行,我們只要建實時開點線段樹,就可以了。 對於詢問,只要在那個顏色的線段樹上詢問就好了。 Code:Code: #include<ios
BZOJ 3531 SDOI2014 旅行 樹鏈剖分
can algorithm 一個點 復雜度 顏色 正常 track log case 題目大意:給定一棵樹,每一個點有一個權值和一個顏色。多次改變一些點的權值和顏色,多次求一條路徑上與起點和終點顏色同樣的點的權值和以及權
【題解】SDOI2014旅行
一點 com col new 旅行 題解 cnp || name 洛谷P3313 大概是一道樹鏈剖分的裸題。可以看出如果不是查詢相同宗教的這一點,就和普通的樹鏈剖分毫無兩樣了。所以針對每一個宗教都單獨開一棵線段樹,變成單點修改+區間查詢。只不過宗教數目很多,空間消耗太大所以
BZOJ 3531 [Sdoi2014]旅行
end har change check cmp pan ostream father continue 題解: 解法1: 樹鏈剖分一下,對每條鏈建立一顆Splay 以宗教為第一關鍵字,深度為第二關鍵字建立 查詢相當於Splay的一個區間 修改相當於刪除一個節點,加入一個節
洛谷 P3313 [SDOI2014]旅行 解題報告
HA 發生 間隔 如果 節省空間 query tro oid 問題 P3313 [SDOI2014]旅行 題目描述 S國有N個城市,編號從1到N。城市間用N-1條雙向道路連接,滿足從一個城市出發可以到達其它所有城市。每個城市信仰不同的宗教,如飛天面條神教、隱形獨角獸教、絕地
洛谷 P3313 [SDOI2014]旅行 樹鏈剖分+動態開點線段樹
P3313 這個題要根據每個城市信仰的宗教建線段樹,但是這樣的話最多會有1e5個線段樹,所以要動態開點(其實就是主席樹思想),先把樹用重鏈剖分,剖出來每個點有線上段樹上對應的區間,所以線段樹共用這一套區間,問題就簡單了,至於修改城市的宗教,只需把原來宗教那個線段樹的對應區間清0,在修改後宗教
luogu_P3313 [SDOI2014]旅行
傳送門 Solution 第二次學習可持久化線段樹 打了一道裸題來練習一下…… 對於每個宗教都可以開一個主席樹 基礎操作 樹剖lca Code #include<bits/stdc++.h> #define ll long
BZOJ 3531: [Sdoi2014]旅行
這題就是樹鏈剖分,對於多種宗教就開多個線段樹,動態開點就好了。 記得卡記憶體 然而一個城市的宗教變了之後還能在變回來,導致我調了一下午。。。 #include<cstdio> #include<cstring> #include<algorithm> #include
[SDOI2014]旅行
P3313 [SDOI2014]旅行 思路 有點噁心咯 每個信仰開一顆線段樹記錄 修改或者查詢的時候去那一顆信仰線段樹中查詢就好 必須動態開點線段樹 沒有區間修改還算好寫 錯誤 查詢跳鏈寫錯了 #include <bits/stdc++.h> #define FOR(i,a,b) for
|BZOJ 3531|樹鏈剖分|動態開點線段樹|[Sdoi2014]旅行
樹剖以後每個宗教建立一棵線段樹,節點太多用傳統方法開陣列肯定不行,這裡進行改進,使用了動態開點線段樹,即需要這個點再開這個點。 #include<cstdio> #include<cstring> #include<alg
【[SDOI2014]旅行】
聽說這是動態開點主席樹的板子題,但是發現我還不會,於是就來寫一寫 其實跟主席樹一個樣子的 這裡就是存個板子吧 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm>
bzoj3531【SDOI2014】旅行
pop data- con time mono bzoj3531 www family swa 3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 850 Solved
CodeVS 1036 商務旅行
height 祖先 memset 商務 最近公共祖先 pri nbsp nsh return 最近一邊轉c++一邊學算法,因為GDOI好像考了LCA,不會寫怎麽辦呢?(當然是爆零得到教訓後再來學啊..) 題目大意:給一棵樹,求經過給定結點的最小費用。。 算法:帶權LCA?倍
【BZOJ1570】[JSOI2008]Blue Mary的旅行 動態加邊網絡流
efi 一次 第一次 dfs name jsoi2008 網絡公司 data cstring 【BZOJ1570】[JSOI2008]Blue Mary的旅行 Description 在一段時間之後,網絡公司終於有了一定的知名度,也開始收到一些訂單,其中最大的一宗來自B
洛谷P1027 Car的旅行路線 計算幾何 圖論最短路
name ani 但是 ret sqrt bsp include struct == 題意 求某城到某城的最小花費 一個城中有四個機場,一個城中的機場相互可達,用公路到達,但是不同城的公路的單位路程的費不同,兩個不同城的機場(我不知道相同城可不可以)可以通過機場到達,且飛機
[NOIP2012] 開車旅行
[0 spa play long b+ pac deque 其中 include 【題目描述】 小A 和小B決定利用假期外出旅行,他們將想去的城市從1到N 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i的海拔高度為Hi,城市 i 和
BZOJ 2157 旅行(樹鏈剖分碼農題)
tac pragma code vector zoj pla none close tag 寫了5KB,1發AC。。。 題意:給出一顆樹,支持5種操作。 1.修改某條邊的權值。2.將u到v的經過的邊的權值取負。3.求u到v的經過的邊的權值總和。4.求u到v的經過的邊的權值最
一個人的旅行 HDU杭電2066【dijkstra算法 || SPFA】
個數 strong -s stdio.h rip include tom trac 第一次 http://acm.hdu.edu.cn/showproblem.php?pid=2066 Problem Description 盡管草兒是個路癡(就是在杭電待了一
【NOIP2012】開車旅行
algo sam time mat row 不同的 blog -- 但是 Description 小A 和小B決定利用假期外出旅行,他們將想去的城市從1到N 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i的海拔高度為Hi,城市