ACM ICPC China final G Pandaria
ACM ICPC China final G Pandaria
题意:给一张\(n\)个点\(m\)条边的无向图,\(c[i]\)代表点\(i\)的颜色,每条边有一个权值
现在有q个询问如下
u w代表从点u出发,每次只能走权值不超过w的边,经过的颜色中次数最多的是哪种颜色,若有多种,输出编号最小的。
$ 1<=n<=1e5$
$ 1<=m,q<=2e5$
$ 1<=c_i<=n$
$ 1<=w<=1e6$
ps:强制在线
思路: 把边从小到大排序,依次合并,现在就是如何维护每个连通块的答案了。
用主席树维护区间最大值和合并操作,查询就是二分最大值的最左位置
如果这题不强制在线的话,那么我们可以把查询按w从小大排序,模拟过去即可
强制在线就多了一些东西,考虑合并的过程,其实是一颗自底向上的树,越往上边权越大
前面主席树已经算出每个结点的答案,如何找到要查询的历史版本,通过pa数组自底向上倍增即可
#include<bits/stdc++.h>
#define P pair<int,int>
#define LL long long
#define ls(i) seg[i].lc
#define rs(i) seg[i].rc
using namespace std;
const int mod = 1e9 + 7;
const int N = 1e5 + 1;
const int M = 2 * N;
const int maxn = 3 * N;
const int maxh = 25;
int n, m,tott;
int c[N];
int ans[maxn];
struct Tree{
int ls, rs, w;
}tree[maxn];
struct node{
int lc,rc,cnt;
}seg[maxn * maxh];///主席树维护的区间的最大值,二分查询最大值所在的最左位置
int root[maxn * maxh];
struct Edge{
int u, v, w;
Edge(){};
bool operator<(const Edge&rhs)const{
return w < rhs.w;
}
}e[M];
void pushup(int rt){
seg[rt].cnt = max(seg[ls(rt)].cnt,seg[rs(rt)].cnt);
}
void update(int &rt,int l,int r,int pos,int val){
seg[++tott] = seg[rt];
rt = tott;
if(l == r){
seg[rt].cnt += val;
return ;
}
int m = (l + r) >> 1;
if(pos <= m) update(ls(rt),l,m,pos,val);
else update(rs(rt),m+1,r,pos,val);
pushup(rt);
}
int query(int rt,int l,int r){
if(l == r) return l;
int m = (l + r) >> 1;
if(seg[ls(rt)].cnt >= seg[rs(rt)].cnt) return query(ls(rt),l,m);
return query(rs(rt),m+1,r);
}
int Merge(int rt1,int rt2,int l,int r){
if(!rt1 || !rt2) return rt1 + rt2;///最多只有n个点保证了合并的复杂度科学
if(l == r){
seg[rt1].cnt += seg[rt2].cnt;
return rt1;
}
int m = l + r >> 1;
ls(rt1) = Merge(ls(rt1),ls(rt2),l,m);
rs(rt1) = Merge(rs(rt1),rs(rt2),m+1,r);
pushup(rt1);
return rt1;
}
int pa[maxn][maxh];
int Find(int x){
return pa[x][0] == x?x:pa[x][0] = Find(pa[x][0]);
}
int ask(int u,int w){ ///倍增找接近的历史版本的答案
for(int i = maxh - 1;i >= 0;i--) if(pa[u][i] && tree[pa[u][i]].w <= w) u = pa[u][i];
return ans[u];
}
int main(){
int T, cas = 1;
cin>>T;
while(T--){
scanf("%d%d",&n,&m);
tott = 0;
for(int i = 1;i <= n;i++) {
scanf("%d",c + i);
root[i] = root[0];
update(root[i],1,n,c[i],1);
pa[i][0] = i;
tree[i].w = 0; ///叶子结点权值为0
ans[i] = query(root[i],1,n);
}
for(int i = 0;i < m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
int tot = n;
sort(e, e + m);
for(int i = 0;i < m;i++){
int u = Find(e[i].u), v = Find(e[i].v), w = e[i].w;
if(u == v) continue;
tree[++tot].w = w;///合并得到新的父结点
tree[tot].ls = u, tree[tot].rs = v;///两个孩子
pa[tot][0] = pa[u][0] = pa[v][0] = tot;
root[tot] = Merge(root[u],root[v],1,n);
ans[tot] = query(root[tot],1,n);
}
for(int i = n + 1;i <= tot;i++) pa[tree[i].ls][0] = pa[tree[i].rs][0] = i;///前面为路径压缩的用途,现在改为上一级祖先用途
for(int i = 1;i <= tot;i++) pa[i][0] = pa[i][0] == i?0:pa[i][0];
for(int i = 1;i < maxh;i++)
for(int j = 1;j <= tot;j++) pa[j][i] = pa[pa[j][i-1]][i-1];
int q, last = 0, u, w;
printf("Case #%d:\n",cas++);
scanf("%d",&q);
while(q--){
scanf("%d%d",&u,&w);
u ^= last, w ^= last;
printf("%d\n",last = ask(u,w));
}
}
return 0;
}
ACM ICPC China final G Pandaria的更多相关文章
- 洪水!(Flooded! ACM/ICPC World Final 1999,UVa815)
题目描述:竞赛入门经典的习题4-10 解题思路:1.把各个网格想象成一个数组 2.排序 3.雨水总体积去铺满 //太懒了只写了求海拔 #include <stdio.h> #define ...
- 【转】lonekight@xmu·ACM/ICPC 回忆录
转自:http://hi.baidu.com/ordeder/item/2a342a7fe7cb9e336dc37c89 2009年09月06日 星期日 21:55 初识ACM最早听说ACM/ICPC ...
- ACM ICPC 2015 Moscow Subregional Russia, Moscow, Dolgoprudny, October, 18, 2015 G. Garden Gathering
Problem G. Garden Gathering Input file: standard input Output file: standard output Time limit: 3 se ...
- 2017 ACM/ICPC Asia Regional Shenyang Online spfa+最长路
transaction transaction transaction Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 132768/1 ...
- 2017 ACM/ICPC Shenyang Online SPFA+无向图最长路
transaction transaction transaction Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 132768/1 ...
- 2014嘉杰信息杯ACM/ICPC湖南程序设计邀请赛暨第六届湘潭市程序设计竞赛
比赛链接: http://202.197.224.59/OnlineJudge2/index.php/Contest/problems/contest_id/36 题目来源: 2014嘉杰信息杯ACM ...
- ACM ICPC 2015 Moscow Subregional Russia, Moscow, Dolgoprudny, October, 18, 2015 D. Delay Time
Problem D. Delay Time Input file: standard input Output file: standard output Time limit: 1 second M ...
- 【转】ACM/ICPC生涯总结暨退役宣言—alpc55
转自:http://hi.baidu.com/accplaystation/item/ca4c2ec565fa0b7fced4f811 ACM/ICPC生涯总结暨退役宣言—alpc55 前言 早就该写 ...
- hduoj 4706 Children's Day 2013 ACM/ICPC Asia Regional Online —— Warmup
http://acm.hdu.edu.cn/showproblem.php?pid=4706 Children's Day Time Limit: 2000/1000 MS (Java/Others) ...
随机推荐
- 关于使用js下载图片
使用js进行图片下载是很常见的需求,但是解决起来却不是那么顺利. 服务器返回了一个图片地址,网上一搜基本都是用a标签的download属性,但是兼容性实在是很差.这里推荐使用blob. 上代码: va ...
- 采坑笔记——mysql的order by和limit排序问题
背景说明 今天写出一个十分弱智的bug,记录一下,提醒自己以后别这种犯错,不怕丢人哈~ 在写一个分页查询记录的sql时,要根据添加的时间逆序分页输出,之前的写法是酱紫 select record.a, ...
- FreeBSD--如何最有效率的安装软件
Freebsd 下如何最有效率的安装软件 From <https://www.cnblogs.com/apexchu/p/4131821.html> FreeBSD的默认下载工具是fetc ...
- Laravel5.5.x集成Swagger (L5-Swagger) 只讲Laravel5.5.x的集成,laravel其他版本请自行研究或参考github上的说明
--------上图 截取自Github 官网上的安装参考----------------------------------------------------------------------- ...
- LINUX操作系统知识:进程与线程详解
当一个程序开始执行后,在开始执行到执行完毕退出这段时间内,它在内存中的部分就叫称作一个进程. Linux 是一个多任务的操作系统,也就是说,在同一时间内,可以有多个进程同时执行.我们大家常用的单CPU ...
- 创建控制器view的几种方式
1. 根据storyboard的描述创建 2. 通过xib的描述创建 3. 通过代码创建控制器的view self.window = [[UIWindow alloc] initWithFrame:[ ...
- C语言字符篇(一)字符串转换函数
#include <stdlib.h> double atof(const char *nptr); 将字符串转换成双精度浮点数 int atoi(const char *npt ...
- scrapy笔记2
cookies的使用: 使用 scrapy.http.cookie.CookieJar 类的extract_cookies方法,CookieJar._cookies就是我们需要的cookies,是一个 ...
- Matplotlib 图表的基本参数设置
1.图名,图例,轴标签,轴边界,轴刻度,轴刻度标签 # 图名,图例,轴标签,轴边界,轴刻度,轴刻度标签等 df = pd.DataFrame(np.random.rand(10,2),columns= ...
- 为 dll (类库) 解决方案添加测试项目
解决方案中新建项目, 添加引用, "解决方案" -> "项目", 选中即可, 而非直接添加 dll, 这会导致编译出错