BZOJ-3531-旅行

描述

http://www.lydsy.com/JudgeOnline/problem.php?id=3531


分析

  • 刚拿到这个题时看到可以更改信仰的宗教, 也就是可以改变路径, 以为是动态树的题目(动态树不会), 后来发现都用的树链剖分, 为每个宗教建立一个线段树. 表示很神奇.
  • 宗教数 <= 10^5, 每个宗教建立一个线段树, 线段树又一般开到四倍空间… 按我平常写线段树的方法肯定不行了. 于是从 HZWER 的博客里学到了动态的线段树, 需要访问某结点时给它分配编号, 记录结点的左右子结点编号而不是用o<<1表示o的左结点, o<<1^1表示o的右结点的方法. 有点指针的感觉.
  • 一开始我卡在不知道怎么修改信仰宗教上, 看 HZWER 发现很简单, 把结点在最初信仰的宗教的线段树里的值修改为0, 再在改变后的信仰宗教的线段树里把值修改为原来的值.
  • 这道题我调了很长时间, 直到最后发现一个最关键的错误出在查询上.

    以查询和为例, 我一开始是这么写的 :

int ask_sum(int x, int y)
{
    int ret = 0;
    while(top[x] != top[y]) {
        if(dep[top[x]] < dep[top[y]]) swap(x, y); // top
        ret += query_sum(roots[c[x]], 1, n, tid[top[x]], tid[x]);
        x = fa[top[x]];
    }

if(dep[x] > dep[y]) swap(x, y);
    ret += query_sum(roots[c[x]], 1, n, tid[x], tid[y]);
    return ret;
}
  • 这里c[x]表示x城市信仰的宗教, 当x改变时, c[x]势必会改变, 但我们要查找的线段树始终是不变的. 所以要记录x最初的线段树的根结点, 而不能每次都用roots[c[x]]来获取.

    改后 :

int ask_sum(int x, int y)
{
    int ret = 0, cx = c[x]; // here
    while(top[x] != top[y]) {
        if(dep[top[x]] < dep[top[y]]) swap(x, y); // top
        ret += query_sum(roots[cx], 1, n, tid[top[x]], tid[x]);
        x = fa[top[x]];
    }

  if(dep[x] > dep[y]) swap(x, y);
    ret += query_sum(roots[cx], 1, n, tid[x], tid[y]);
    return ret;
}
  • 发现vector存图真的没邻接表好, 既费时间又费空间, 所以以后改用数组模拟邻接表来存了.

代码

https://code.csdn.net/snippets/611472

时间: 2024-10-20 22:06:33

BZOJ-3531-旅行的相关文章

BZOJ.3531.旅行(树链剖分 动态开点)

题目链接 无优化版本(170行): /* 首先树剖可以维护树上的链Sum.Max 可以对每个宗教建一棵线段树,那这题就很好做了 不过10^5需要动态开点 (不明白为什么nlogn不需要回收就可以 不是每个Insert加log个节点?) 操作修改完更改原数列!盲人..少玩rts.. */ #include<cstdio> #include<cctype> #include<algorithm> #define gc() getchar() #define now node

[BZOJ 3531] [Sdoi2014] 旅行 【离线+LCT】

题目链接:BZOJ - 3531 题目分析 题目询问一条路径上的信息时,每次询问有某种特定的文化的点. 每个点的文化就相当于一种颜色,每次询问一条路径上某种颜色的点的信息. 可以使用离线算法, 类似于“郁闷的小 J ” 那道题目.将各种操作和询问按照颜色为第一关键字,时间为第二关键字排序. 那么修改颜色的操作就相当于在原颜色中是删点,在新颜色中是加点. 处理完一种颜色的操作后,要将这个颜色的点都做一次删除操作,这样,对于处理下一种颜色,树就又是空的了. 这种题,思考的时候有点晕,写代码的时候非常

BZOJ 3531(树链剖分+线段树)

Problem 旅行 (BZOJ 3531) 题目大意 给定一颗树,树上的每个点有两个权值(x,y). 要求维护4种操作: 操作1:更改某个点的权值x. 操作2:更改某个点的权值y. 操作3:求a-->b路径上所有x属性与a,b相同的点y属性的和. 操作4:求a-->b路径上所有x属性与a,b相同的点y属性的最大值. N,Q ,x <= 10^5  ,  y <= 10^4 解题分析 由于x属性的范围较大,无法直接统计. 考虑每次修改为单点修改,询问时只对相同x属性的询问. 因此,

BZOJ 1050 旅行comf(枚举最小边-并查集)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1050 题意:给出一个带权图.求一条s到t的路径使得这条路径上最大最小边的比值最小? 思路:将边排序.枚举最小边,然后将边一个一个插到并查集里,s和t联通时计算更新答案. struct node { int u,v,w; void get() { RD(u,v,w); } }; int cmp(node a,node b) { return a.w<b.w; } int n,m,s,t;

bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)

3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 876  Solved: 446[Submit][Status][Discuss] Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表 各种宗教,  S国的居民常常旅行.旅行时他们总

【BZOJ 3531】 [Sdoi2014]旅行

3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 575 Solved: 303 [Submit][Status][Discuss] Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行.旅行时他们总会走

[BZOJ 3531][Sdoi2014]旅行(树链剖分+线段树)

Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表各种宗教,  S国的居民常常旅行.旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿.当然旅程的终点也是信仰与他相同的城市.S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值. 在S国的历史

[BZOJ]3531: [Sdoi2014]旅行

题目大意:给定一棵树,每个点有颜色和权值,支持修改一个点的颜色和权值,查询一条链上某种颜色的和与最大值.(n<=10^5) 思路:树剖一下,每种颜色开一棵线段树,动态开点,时间复杂度O(nlogn^2),空间复杂度O(nlogn). #include<cstdio> #include<algorithm> using namespace std; inline int read() { int x;char c; while((c=getchar())<'0'||c&g

BZOJ 3531 SDOI 2014 旅行

题目大意 给出一个树,树上每个节点有两个权值,分别是这个节点的宗教评级和这个节点信仰的宗教.多次修改这两个权值,每次询问树上路径上的点的同一个宗教的最大评级和评级和. 思路 不要想太多,每个宗教建立一颗线段树,空间开不下考虑一下动态节点线段树.之后在每个线段树上维护一下树链剖分就行了. 你们想知道c的取值范围么? [0,10^5] CODE #define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstring> #i

BZOJ 3531 SDOI2014 旅行 树链剖分

题目大意:给定一棵树,每一个点有一个权值和一个颜色.多次改变一些点的权值和颜色,多次求一条路径上与起点和终点颜色同样的点的权值和以及权值最大值 每种颜色开一个线段树 动态开节点 每一个点仅仅建一条链 这样空间复杂度是O(nlogn)的 然后就正常树链剖分即可了 #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm>