sicily 1876. Basic Graph Problem 线段树+并查集+路径压缩

2024-03-06 09:08

本文主要是介绍sicily 1876. Basic Graph Problem 线段树+并查集+路径压缩,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

线段树或者RMQ都可以做,虽然是不是动态变化的,但是用线段树做也不错,,而且最近才开始弄线段树,当练练手。。。

一定要路径压缩的并查集,,不然线性的话,耗时过高。。。

而且不能写递归的路径压缩,我猜得。。。

因为n<=100000,一般20000就会栈爆的,,,,

#include<iostream>

#include<cstdio>
#include<cstring>
using namespace std;
int n;
int w[100100];
struct node{
int left;
int right;
int min;
int max;
}seg[4*100000];
int father[100010];
void build(int p,int x,int y){
seg[p].left = x;
seg[p].right = y;
if(x==y){
// seg[p].left = seg[p].right = x;
seg[p].max = seg[p].min = w[x];
return ;
}
int mid = (x+y)/2;
build(2*p,x,mid);
build(2*p+1,mid+1,y);
int minl,minr,maxl,maxr;
minl = seg[2*p].min,maxl = seg[2*p].max;
minr = seg[2*p+1].min,maxr = seg[2*p+1].max;
if(minl<minr)seg[p].min = minl;
else seg[p].min = minr;
if(maxl>maxr)seg[p].max = maxl;
else seg[p].max = maxr;
}
void find(int p,int x,int y,int &min,int &max){
if(x==seg[p].left && y==seg[p].right){
min = seg[p].min;
max = seg[p].max;
return ;
}
int mid = (seg[p].left+seg[p].right)/2;
if(mid>=y){
find(2*p,x,y,min,max);
}else if(mid<x){
find(2*p+1,x,y,min,max);
}else {
int min1,min2,max1,max2;
find(2*p,x,mid,min1,max1);
find(2*p+1,mid+1,y,min2,max2);
min = min1<min2?min1:min2;
max = max1>max2?max1:max2;
return ;
}
}
int f(int a){///查找过程路径压缩
int i = a;
while(a!=father[a])a = father[a];
while(i!=a){
int tmp = father[i];
father[i] = a; 
i = tmp;
}
return a;


}
void union_set(int u,int v){
int a = f(u);
int b = f(v);
if(a==b)return ;
if(a<b)father[b] = a;
else father[a] = b;

}
int main(){
int casenum = 0;
while(scanf("%d",&n)!=EOF){

if(casenum)printf("\n");
printf("CASE %d\n",++casenum);
for(int i = 1;i<=n;i++){
scanf("%d",&w[i]);
father[i] = i;
}
build(1,1,n);
int m;
scanf("%d",&m);
int u,v;
int min,max;
for(int i = 1;i<=m;i++){
scanf("%d%d",&u,&v);
find(1,u,v,min,max);
/// printf("%d %d\n",min,max);
union_set(min,max);
}
int k;
scanf("%d",&k);
for(int i = 0;i<k;i++){
scanf("%d%d",&u,&v);
if(f(u)==f(v))printf("YES\n");
else printf("NO\n");
}
}
return 0;
}

这篇关于sicily 1876. Basic Graph Problem 线段树+并查集+路径压缩的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/779526

相关文章

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

hdu1565(状态压缩)

本人第一道ac的状态压缩dp,这题的数据非常水,很容易过 题意:在n*n的矩阵中选数字使得不存在任意两个数字相邻,求最大值 解题思路: 一、因为在1<<20中有很多状态是无效的,所以第一步是选择有效状态,存到cnt[]数组中 二、dp[i][j]表示到第i行的状态cnt[j]所能得到的最大值,状态转移方程dp[i][j] = max(dp[i][j],dp[i-1][k]) ,其中k满足c

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

hdu2544(单源最短路径)

模板题: //题意:求1到n的最短路径,模板题#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#i

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

uva 10025 The ? 1 ? 2 ? ... ? n = k problem(数学)

题意是    ?  1  ?  2  ?  ...  ?  n = k 式子中给k,? 处可以填 + 也可以填 - ,问最小满足条件的n。 e.g k = 12  - 1 + 2 + 3 + 4 + 5 + 6 - 7 = 12 with n = 7。 先给证明,令 S(n) = 1 + 2 + 3 + 4 + 5 + .... + n 暴搜n,搜出当 S(n) >=