BZOJ4999 JZOJ5112【usaco2017_Mar Platinum】Switch Grass


Farmer John has recently been experimenting with cultivating different types of grass on his farm, realizing that different types of cows like different types of grass. However, he must be careful to ensure that different types of grass are planted sufficiently far away from each-other, in order to prevent them from being inextricably mixed.

FJ’s farm consists of N fields (1N200,000), where M pairs of fields are connected by bi-directional pathways (1M200,000). Using these pathways, it is possible to walk from any field to any other field. Each pathway has an integer length in the range 11,000,000. Any pair of fields will be linked by at most one direct pathway.

In each field, FJ initially plants one of K types of grass (1KN). Over time, however, he might decide to switch the grass in some field to a different type. He calls this an “update” operation. He might perform several updates over the course of time, which are all cumulative in nature.

After each update, FJ would like to know the length of the shortest path between two fields having different grass types. That is, among all pairs of fields having different grass types, he wants to know which two are closest. Ideally, this number is large, so he can prevent grass of one type from mixing with grass of another type. It is guaranteed that the farm will always have at least two fields with different grass types.

In 30 percent of the input cases, each field will be directly connected to at most 10 pathways.


The first line of input contains four integers, N, M, K, and Q, where Q is the number of updates (1Q200,000). The next M lines describe the paths; each one contains three integers A, B, and L, indicating a path from field A to field B (both integers in the range 1N) of length L. The next line indicates the initial type of grass growing in each field (N integers in the range 1K). Finally, the last Q lines each describe an update, specified by two integers A and B, where the grass in field A is to be updated to type B.


For each update, print the length of the shortest path between two fields with different types of grass, after the update is applied.

Sample Input

3 2 3 4
1 2 3
2 3 1
1 1 2
3 3
2 3
1 2
2 2

Sample Output








然后怎么就发现怎么是O(n^3 log n)的呢?
颜色用map,堆用multiset,然后就发现是O(n log n)。


#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;

const int Maxn = 200005, INF = 1e9;

typedef pair<int, int> P;
typedef multiset<int> T;
typedef map<int, T> M;
M a[Maxn];
multiset<P> b[Maxn];
T c;

struct node {
    int x, y, z;
int n, m, k, q, x, y, z, color[Maxn], f[Maxn], bz[Maxn], fa[Maxn], fav[Maxn], d[Maxn];
int final[Maxn], tot;
struct egde {
    int to, next, v;
}e[Maxn * 2];

void read(int &x) {
    char ch = ' '; x = 0;
    for(;ch < '0' || ch > '9'; ch = getchar());
    for(;ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - 48;

bool rank_b(node a, node b) {return a.z < b.z;}
int find(int x) {return f[x] == x ? x : (f[x] = find(f[x]));}
void link(int x, int y, int z) {
    e[++ tot].next = final[x], e[tot].to = y, e[tot].v = z, final[x] = tot;
    e[++ tot].next = final[y], e[tot].to = x, e[tot].v = z, final[y] = tot;

void Init() {
    scanf("%d %d %d %d", &n, &m, &k, &q);
    fo(i, 1, m) {
        read(bb[i].x); read(bb[i].y); read(bb[i].z);
    fo(i, 1, n) read(color[i]);

multiset<P> :: iterator it;

void Gai_d(int x) {
    if(d[x] != INF) c.erase(c.find(d[x]));
    P v = (*b[x].begin()); it = b[x].begin();
    int o = b[x].size();
    if((v.second == color[x] && o == 1) || !o) d[x] = INF; else {
        if(v.second == color[x]) d[x] = (*(++ it)).first; else d[x] = (*it).first;

void Gai(int x, int y, int z, int bz, int c1, int c2) {
    int u = *a[x][c1].begin(), v = a[x][c1].size();
    if(v) b[x].erase(b[x].find(make_pair(u, c1)));
    if(bz) a[x][c1].erase(a[x][c1].find(z));
    if(!a[x][c1].empty()) b[x].insert(make_pair(, c1));
    if(!a[x][c2].empty()) b[x].erase(b[x].find(make_pair(*a[x][c2].begin(), c2)));
    b[x].insert(make_pair(*a[x][c2].begin(), c2));

void dg_mak(int x) {
    bz[x] = 1;
    for(int k = final[x]; k; k = e[k].next) {
        int y = e[k].to, z = e[k].v; if(bz[y]) continue;
        Gai(x, y, z, 0, color[y], color[y]);
        fa[y] = x; fav[y] = z; dg_mak(y);

void Build() {
    sort(bb + 1, bb + m + 1, rank_b);
    fo(i, 1, n) f[i] = i;
    fo(i, 1, m) {
        x = bb[i].x, y = bb[i].y, z = bb[i].z;
        if(find(x) != find(y)) {
            f[f[x]] = f[y];
            link(x, y, z);
    fo(i, 1, n) d[i] = INF;

void End() {
    fo(i, 1, q) {
        read(x); read(y);
        if(fa[x]) Gai(fa[x], x, fav[x], 1, color[x], y);
        color[x] = y; Gai_d(x);
        printf("%d\n", (*c.begin()));

int main() {
    freopen("", "r", stdin);
    freopen("grass.out", "w", stdout);
发布了410 篇原创文章 · 获赞 378 · 访问量 17万+


©️2019 CSDN 皮肤主题: 深蓝海洋 设计师: CSDN官方博客