题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5029

Problem Description
The soil is cracking up because of the drought and the rabbit kingdom is facing a serious famine. The RRC(Rabbit Red Cross) organizes the distribution of relief grain in the disaster area.

We can regard the kingdom as a tree with n nodes and each node stands for a village. The distribution of the relief grain is divided into m phases. For each phases, the RRC will choose a path of the tree and distribute some relief grain of a certain type for every village located in the path.

There are many types of grains. The RRC wants to figure out which type of grain is distributed the most times in every village.

 
Input
The input consists of at most 25 test cases.

For each test case, the first line contains two integer n and m indicating the number of villages and the number of phases.

The following n-1 lines describe the tree. Each of the lines contains two integer x and y indicating that there is an edge between the x-th village and the y-th village.
  
The following m lines describe the phases. Each line contains three integer x, y and z indicating that there is a distribution in the path from x-th village to y-th village with grain of type z. (1 <= n <= 100000, 0 <= m <= 100000, 1 <= x <= n, 1 <= y <= n, 1 <= z <= 100000)

The input ends by n = 0 and m = 0.

 
Output
For each test case, output n integers. The i-th integer denotes the type that is distributed the most times in the i-th village. If there are multiple types which have the same times of distribution, output the minimal one. If there is no relief grain in a village, just output 0.
 
题目大意:有一棵n个点的数,有m个操作,每次给路径path(x, y)分配一个值z。最后问每个点被分配次数最多的值,如有多个输出最小的一个。
思路:首先我们可以注意到,要输出结果只有最后一个,所有操作的顺序都是无关紧要的,我们可以按自己喜欢的顺序来做。
 
这个问题是在树上做的,我们先来简化一下问题,如果这是一维的线段,每次在一个区间上操作,怎么办。
这个问题的解法是,按值建树,对于每一个操作(x, y, z),也就是给区间[x, y + 1)分配资源,可以给 x 标记一个 +z,给 y + 1 标记一个 -z。
按坐标从左往右扫,对于每一个 x,把所有标记压入线段树,然后再求 x 的答案。总体复杂度为O(nlogn)。
 
回到本题的问题,这题是在树上做的,按上面的做法,可以想到,对于操作(x, y, z),求出其lca,把它分为两条链[x, lca],[y, lca)。
然后按dfs序做,此时对于每一个结点,我们在做完它的所有子节点后,要把子节点的所有线段树合并,再加上它自身的标记,再求出这个结点的答案。
但是随意地合并线段树,可能会使得复杂度高达O(n^2logn)。这里采取启发式合并,每次把小的线段树合并到大的线段树上。
不考虑减的标记,标记最多有3n个,那么每个标记被合并之后,它所在的线段树大小至少会增加两倍,那么最多被合并O(logn)次。
在考虑减的标记的时候,虽然上述分析不适用了,但是感觉上减少了标记只会令复杂度降低。所以总复杂度为O(n(logn)^2)。
 
代码(3046MS):
 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> PII; const int MAXV = ;
const int MAXE = MAXV << ;
const int MAXT = MAXV << ; int head[MAXV], ecnt;
int to[MAXE], next[MAXE];
int n, m, maxz; void init() {
memset(head + , -, n * sizeof(int));
ecnt = ;
} void add_edge(int u, int v) {
to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; next[ecnt] = head[v]; head[v] = ecnt++;
} #define mid ((l + r) >> 1)
struct Node {
Node *lson, *rson;
int val, cnt, size;
Node() {
val = cnt = size = ;
}
void update() {
Node *s = lson->cnt >= rson->cnt ? lson : rson;
val = s->val;
cnt = s->cnt;
size = lson->size + rson->size;
}
} *nil;
Node statePool[MAXT * ];
Node *stk[MAXT * ];
int top, scnt; Node* new_node() {
Node *p;
if(top) p = stk[--top];
else p = &statePool[scnt++];
p->lson = p->rson = nil;
p->val = p->cnt = p->size = ;
return p;
} void del_node(Node *p) {
stk[top++] = p;
} void remove(Node *y) {
if(y->lson != nil) remove(y->lson);
if(y->rson != nil) remove(y->rson);
del_node(y);
} void modify(Node *&x, int l, int r, int pos, int val) {
if(x == nil) x = new_node();
if(l == r) {
x->val = l;
x->cnt += val;
x->size = (x->cnt > );
} else {
if(pos <= mid) modify(x->lson, l, mid, pos, val);
if(mid < pos) modify(x->rson, mid + , r, pos, val);
x->update();
}
} void merge(Node *x, Node *y, int l, int r) {
if(y->size != ) {
if(l == r) {
modify(x, , maxz, l, y->cnt);
} else {
merge(x, y->lson, l, mid);
merge(x, y->rson, mid + , r);
}
}
} Node* merge(Node *x, Node *y) {
if(x->size < y->size) swap(x, y);
merge(x, y, , maxz);
remove(y);
return x;
} vector<PII> query[MAXV];
struct Modify {
int u, v, c, lca;
void read(int i) {
scanf("%d%d%d", &u, &v, &c);
maxz = max(maxz, c);
query[u].push_back(make_pair(v, i));
query[v].push_back(make_pair(u, i));
}
} ask[MAXV];
int fa[MAXV];
bool vis[MAXV]; int find_set(int x) {
return fa[x] == x ? x : fa[x] = find_set(fa[x]);
} void lca(int u, int f) {
for(int p = head[u]; ~p; p = next[p]) {
int &v = to[p];
if(v == f || vis[v]) continue;
lca(v, u);
fa[v] = u;
}
vis[u] = true;
for(vector<PII>::iterator it = query[u].begin(); it != query[u].end(); ++it) {
if(vis[it->first]) {
ask[it->second].lca = find_set(it->first);
}
}
} vector<PII> pre[MAXV], nxt[MAXV];
int ans[MAXV]; Node* dfs(int u, int f) {
Node *x = new_node();
for(int p = head[u]; ~p; p = next[p]) {
int v = to[p];
if(v == f) continue;
x = merge(x, dfs(v, u));
}
for(vector<PII>::iterator it = pre[u].begin(); it != pre[u].end(); ++it)
modify(x, , maxz, it->first, it->second);
ans[u] = x->val;
for(vector<PII>::iterator it = nxt[u].begin(); it != nxt[u].end(); ++it)
modify(x, , maxz, it->first, it->second);
return x;
} void solve() {
for(int i = ; i <= n; ++i) {
fa[i] = i;
vis[i] = false;
pre[i].clear(); nxt[i].clear();
}
lca(, );
for(int i = ; i < m; ++i) {
const Modify &t = ask[i];
pre[t.u].push_back(make_pair(t.c, ));
pre[t.v].push_back(make_pair(t.c, ));
pre[t.lca].push_back(make_pair(t.c, -));
nxt[t.lca].push_back(make_pair(t.c, -));
}
top = scnt = ;
Node *p = dfs(, );
if(p != nil) remove(p); for(int i = ; i <= n; ++i)
printf("%d\n", ans[i]);
} int main() {
nil = new Node();
nil->lson = nil->rson = nil; while(scanf("%d%d", &n, &m) != EOF) {
if(n == && m == ) break;
init();
for(int i = , u, v; i < n; ++i) {
scanf("%d%d", &u, &v);
add_edge(u, v);
}
for(int i = ; i <= n; ++i) query[i].clear();
maxz = ;
for(int i = ; i < m; ++i) ask[i].read(i);
solve();
}
}

HDU 5029 Relief grain(离线+线段树+启发式合并)(2014 ACM/ICPC Asia Regional Guangzhou Online)的更多相关文章

  1. HDU 4747 Mex(线段树)(2013 ACM/ICPC Asia Regional Hangzhou Online)

    Problem Description Mex is a function on a set of integers, which is universally used for impartial ...

  2. HDU 4719 Oh My Holy FFF(DP+线段树)(2013 ACM/ICPC Asia Regional Online ―― Warmup2)

    Description N soldiers from the famous "*FFF* army" is standing in a line, from left to ri ...

  3. HDU 5052 Yaoge’s maximum profit 光秃秃的树链拆分 2014 ACM/ICPC Asia Regional Shanghai Online

    意甲冠军: 特定n小点的树权. 以下n每一行给出了正确的一点点来表达一个销售点每只鸡价格的格 以下n-1行给出了树的侧 以下Q操作 Q行 u, v, val 从u走v,程中能够买一个鸡腿,然后到后面卖 ...

  4. hdu 5016 点分治(2014 ACM/ICPC Asia Regional Xi'an Online)

    Mart Master II Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  5. HDU 5889 Barricade 【BFS+最小割 网络流】(2016 ACM/ICPC Asia Regional Qingdao Online)

    Barricade Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  6. HDU 4729 An Easy Problem for Elfness(主席树)(2013 ACM/ICPC Asia Regional Chengdu Online)

    Problem Description Pfctgeorge is totally a tall rich and handsome guy. He plans to build a huge wat ...

  7. HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)

    Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node ...

  8. HDU 4757 Tree(可持久化字典树)(2013 ACM/ICPC Asia Regional Nanjing Online)

    Problem Description   Zero and One are good friends who always have fun with each other. This time, ...

  9. HDU 4069 Squiggly Sudoku(DLX)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4069 Problem Description Today we play a squiggly sud ...

随机推荐

  1. nrf51822裸机教程-PWM

    先简单介绍一下PWM的原理. 原理很简单. 假设COUNTER是个从0开始递增的计数器.  我们设置两个值 counter0 和counter1 在 COUNTER 计数到counter0的值时候翻转 ...

  2. Erlang ERTS的Trap机制的设计及其用途

    出处:http://mryufeng.iteye.com/blog/334744 erlang的trap机制在实现中用的很多,在费时的BIF操作中基本上都可以看到.它的实现需要erl vm的配合.它的 ...

  3. SQL Server存储机制

    1.区段 区段(extent)是用来为表和索引分配空间的基本存储单元.它由8个连续的64KB数据页组成. 基于区段(而不是实际使用空间)分配空间的概念的要点: 一旦区段已满,那么下一记录将要占据的空间 ...

  4. 针对JD-GUI

    switch(0){ case 1001: JSONObject jsoObj; String data = null; boolean isclose = false; try{ jsoObj = ...

  5. Nagios Looking Glass 本地文件包含漏洞

    漏洞名称: Nagios Looking Glass 本地文件包含漏洞 CNNVD编号: CNNVD-201310-682 发布时间: 2013-10-31 更新时间: 2013-10-31 危害等级 ...

  6. js实现选项卡

    通过JavaScript实现如上选项卡切换的效果. 实现思路: 一.HTML页面布局 选项卡标题使用ul..li 选项卡内容使用div 二.CSS样式制作 整个选项卡的样式设置 选项卡标题的样式设置 ...

  7. Java学习-020-Properties 判断是否存在对应的 key 项

    在日常的脚本编写过程中,通常会判断配置文件中是否存在对应的配置项,以判断是否执行相应的业务逻辑. 小二上码...若有不足之处,敬请大神指正,不胜感激! 判断是否存在 key 项(配置项)的方法源码如下 ...

  8. imx6 启动 init进程

    之前不知道imx6内核是怎么启动文件系统的init进程,查了下资料,记录于此,以后再来补充. kernel/init/main.c static noinline int init_post(void ...

  9. meta的学习记录

    meta的学习记录 最近再学响应式的布局,就先来总结一下我们的viewport. 什么是viewport呢? 手机浏览器是把页面放在一个虚拟的“窗口”(viewport)中,通常这个虚拟的“窗口”(v ...

  10. DBCC TRACEON/TRACEOFF/TRACESTATUS

    1. enable trace DBCC TRACEON ( trace# [ ,...n ][ , -1 ] ) [ WITH NO_INFOMSGS ] trace# Is the number ...