BZOJ3307: 雨天的尾巴
阿新 • • 發佈:2018-06-05
都是 UC IT != log struct || turn git
Submit: 1004 Solved: 400
[Submit][Status][Discuss]
8 6
10 6
18 6
20 10
7 20
2 18
19 8
1 6
14 20
16 10
13 19
3 14
17 18
11 19
4 11
15 14
5 18
9 10
12 15
11 14 87
12 1 87
14 3 84
17 2 36
6 5 93
17 6 87
10 14 93
5 16 78
6 15 93
15 5 16
11 8 50
17 19 50
5 4 87
15 20 78
1 17 50
20 13 87
7 15 22
16 11 94
19 8 87
18 3 93
13 13 87
2 1 87
2 6 22
5 20 84
10 12 93
18 12 87
16 10 93
8 17 93
14 7 36
7 4 22
5 9 87
13 10 16
20 11 50
9 16 84
10 17 16
19 6 87
12 2 36
20 9 94
9 2 84
14 1 94
5 5 94
8 17 16
12 8 36
20 17 78
12 18 50
16 8 94
2 19 36
10 18 36
14 19 50
4 12 50
中文題意簡單易懂 不再敘述
題解: 很明顯我們考慮到運用樹上差分的思想 加入這個元素等於在u,v位置加入 刪除等於在lca(u,v)和fa[lca(u,v)]的地方-1 這樣問題就轉化成 從葉子節點dfs將這些點操作 並查詢區間num最大且vul最小的值即可 這樣我們可以通過線段樹維護 然後本題的一個難點就是線段樹合並了吧 講道理 以前的合並的題都是啟發式合並 但是這個題有個性質就是你用線段樹維護 那麽你就只需要將都有的節點從小到上更新 沒有的之間連上去即可 然後就做完了 復雜度均攤下來應該是nlogn 空間復雜度同理也是nlogn
#include <bits/stdc++.h> #define pii pair<int,int> const int MAXN=1e5+10; #define ll long long using namespace std; int n,m; vector<int>vec[MAXN]; ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar(); return x*f; } int fa[MAXN],num[MAXN],dep[MAXN],son[MAXN]; void dfs1(int v,int pre,int deep){ num[v]=1;fa[v]=pre;dep[v]=deep+1; for(int i=0;i<vec[v].size();i++){ if(vec[v][i]!=pre){ dfs1(vec[v][i],v,deep+1); num[v]+=num[vec[v][i]]; if(son[v]==-1||num[son[v]]<num[vec[v][i]])son[v]=vec[v][i]; } } } int p[MAXN],fp[MAXN],cnt,tp[MAXN],sz; void dfs2(int v,int td){ p[v]=++cnt;fp[p[v]]=v;tp[v]=td; if(son[v]!=-1)dfs2(son[v],td); for(int i=0;i<vec[v].size();i++){ if(vec[v][i]!=son[v]&&vec[v][i]!=fa[v])dfs2(vec[v][i],vec[v][i]); } } int Lca(int u,int v){ int uu=tp[u];int vv=tp[v]; while(uu!=vv){ if(dep[uu]<dep[vv])swap(uu,vv),swap(u,v); u=fa[uu];uu=tp[u]; } if(dep[u]>dep[v])swap(u,v); return u; } typedef struct que{ int u,v,c,lca; }que; que q[MAXN]; vector<int>v1; vector<pii>v2[MAXN]; typedef struct node{ int num,maxx,l,r; }node; node d[MAXN*16*4];int ans[MAXN],rt[MAXN]; void up(int x){ if(!d[x].l&&!d[x].r)return ; d[x].num=0; if(d[x].l){d[x].num=d[d[x].l].num;d[x].maxx=d[d[x].l].maxx;} if(d[x].r){ if(!d[x].num)d[x].num=d[d[x].r].num,d[x].maxx=d[d[x].r].maxx; else { if(d[x].num<d[d[x].r].num)d[x].num=d[d[x].r].num,d[x].maxx=d[d[x].r].maxx; else if(d[x].num==d[d[x].r].num)d[x].maxx=min(d[x].maxx,d[d[x].r].maxx); } } } int cnt1; void update(int &rt,int l,int r,int t,int vul){ if(!rt)rt=++cnt1; if(l==r){d[rt].num+=vul;d[rt].maxx=l;return ;} int mid=(l+r)>>1; if(t<=mid)update(d[rt].l,l,mid,t,vul); else update(d[rt].r,mid+1,r,t,vul); up(rt); } void merge(int &x,int y,int l,int r){ if(!x&&!y)return ; if(x&&y){ if(l==r){ d[x].num+=d[y].num;return ; } int mid=(l+r)>>1; merge(d[x].l,d[y].l,l,mid); merge(d[x].r,d[y].r,mid+1,r); } else{ if(y)x=y; return ; } up(x); } void dfs(int v){ for(int i=0;i<vec[v].size();i++){ if(vec[v][i]!=fa[v]){ dfs(vec[v][i]); merge(rt[v],rt[vec[v][i]],1,sz); } } for(int i=0;i<v2[v].size();i++){ update(rt[v],1,sz,v2[v][i].first,v2[v][i].second);} // cout<<d[rt[v]].num<<"====:::"<<" "<<v<<endl; // for(int i=0;i<v2[v].size();i++)cout<<v2[v][i].first<<" "<<v2[v][i].second<<endl; if(!d[rt[v]].num)ans[v]=0; else ans[v]=d[rt[v]].maxx; } int main(){ n=read();m=read(); for(int i=1;i<=n;i++)son[i]=-1; int u,v; for(int i=1;i<n;i++)u=read(),v=read(),vec[u].push_back(v),vec[v].push_back(u); dfs1(1,0,0);dfs2(1,1); for(int i=1;i<=m;i++)q[i].u=read(),q[i].v=read(),q[i].c=read(),v1.push_back(q[i].c),q[i].lca=Lca(q[i].u,q[i].v); //for(int i=1;i<=m;i++)cout<<q[i].lca<<" "; //cout<<endl; sort(v1.begin(),v1.end()); sz=unique(v1.begin(),v1.end())-v1.begin(); // built(1,1,sz); for(int i=1;i<=m;i++){ q[i].c=lower_bound(v1.begin(),v1.begin()+sz,q[i].c)-v1.begin()+1,v2[q[i].u].push_back(make_pair(q[i].c,1)); v2[q[i].v].push_back(make_pair(q[i].c,1));v2[q[i].lca].push_back(make_pair(q[i].c,-1)); v2[fa[q[i].lca]].push_back(make_pair(q[i].c,-1)); } dfs(1); for(int i=1;i<=n;i++){ if(!ans[i])puts("0"); else printf("%d\n",v1[ans[i]-1]); } return 0; }
3307: 雨天的尾巴
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1004 Solved: 400
[Submit][Status][Discuss]
Description
N個點,形成一個樹狀結構。有M次發放,每次選擇兩個點x,y
對於x到y的路徑上(含x,y)每個點發一袋Z類型的物品。完成
所有發放後,每個點存放最多的是哪種物品。
Input
第一行數字N,M
接下來N-1行,每行兩個數字a,b,表示a與b間有一條邊
再接下來M行,每行三個數字x,y,z.如題
Output
輸出有N行
每i行的數字表示第i個點存放最多的物品是哪一種,如果有
多種物品的數量一樣,輸出編號最小的。如果某個點沒有物品
則輸出0
Sample Input
20 508 6
10 6
18 6
20 10
7 20
2 18
19 8
1 6
14 20
16 10
13 19
3 14
17 18
11 19
4 11
15 14
5 18
9 10
12 15
11 14 87
12 1 87
14 3 84
17 2 36
6 5 93
17 6 87
10 14 93
5 16 78
6 15 93
15 5 16
11 8 50
17 19 50
5 4 87
15 20 78
1 17 50
20 13 87
7 15 22
16 11 94
19 8 87
18 3 93
13 13 87
2 1 87
2 6 22
5 20 84
10 12 93
18 12 87
16 10 93
8 17 93
14 7 36
7 4 22
5 9 87
13 10 16
20 11 50
9 16 84
10 17 16
19 6 87
12 2 36
20 9 94
9 2 84
14 1 94
5 5 94
8 17 16
12 8 36
20 17 78
12 18 50
16 8 94
2 19 36
10 18 36
14 19 50
4 12 50
Sample Output
87
36
84
22
87
87
22
50
84
87
50
36
87
93
36
94
16
87
50
50
1<=N,M<=100000
1<=a,b,x,y<=N
1<=z<=10^9
BZOJ3307: 雨天的尾巴