(Luogu) P3950 部落冲突 (LCT || 树链剖分)

传送门

解:LCT解决这个就非常直接了,直接断边连边,检查一下连通性就行了。

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define SZ(a) int((a).size())
#define ls ch[x][0]
#define rs ch[x][1]
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int N=3e5+5;
template <typename _Tp> il void read(_Tp&x) {
	char ch;bool flag=0;x=0;
	while(ch=getchar(),!isdigit(ch)) if(ch=='-')flag=1;
	while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
	if(flag) x=-x;
}
//il int Add(int &x,ll y) {return x=x+y>=mod?x+y-mod:x+y;}
//il int Mul(int &x,ll y) {return x=x*y>=mod?x*y%mod:x*y;}
int f[N],ch[N][2],v[N],s[N],st[N],sz[N];
bool r[N];
il bool isroot(int x){
	return ch[f[x]][0]==x || ch[f[x]][1]==x; 
} 
il void pushup(int x){
	sz[x]=sz[ls]+sz[rs]+1; 
}
il void reverse(int x){
	swap(ls,rs),r[x]^=1;
}
il void pushdown(int x){
	if(r[x]){
		if(ls) reverse(ls);
		if(rs) reverse(rs);
		r[x]=0;
	}
}
il void rotate(int x){
	int y=f[x],z=f[y],k=(ch[y][1]==x),w=ch[x][!k];
	if(isroot(y))	ch[z][ch[z][1]==y]=x;
	ch[x][!k]=y,ch[y][k]=w;
	if(w) f[w]=y;
	f[y]=x,f[x]=z;
	pushup(y);
}
il void splay(int x){
	int y=x,z=0;
	st[++z]=y;
	while(isroot(y)) st[++z]=y=f[y];
	while(z) pushdown(st[z--]);
	while(isroot(x)){
		y=f[x],z=f[y];
		if(isroot(y)) rotate((ch[y][0]==x)^(ch[z][0]==y)?x:y);
		rotate(x);
	}
	pushup(x);
}
 
il void access(int x){
	for(int y=0;x;x=f[y=x]){
		splay(x),rs=y,pushup(x);
	}
}
il void makeroot(int x){
	access(x),splay(x);
	reverse(x);
}
il int findroot(int x){//查找在原树的根 
	access(x),splay(x);
	while(ls) pushdown(x),x=ls;
	splay(x);
	return x;
}
il void split(int x,int y){
	makeroot(x);
	access(y),splay(y);
}
//保证合法的情况下 
il void link(int x,int y){
	makeroot(x),f[x]=y;
}
il void cut(int x,int y){
	split(x,y);
	f[x]=ch[y][0]=0;
}

int n,m;
char op[2];
struct node{
	int u,v;
}q[N];
int main() {
	read(n),read(m);
	int x,y,cnt=0;
	for(int i=1;i<=n-1;++i){
		read(x),read(y);
		link(x,y);
	}
	while(m--){
		scanf("%s",op);
		if(op[0]=='Q'){
			read(x),read(y);
			if(findroot(x)==findroot(y)) printf("Yes\n");
			else printf("No\n");
		}
		else if(op[0]=='C'){
			read(x),read(y);
			q[++cnt]={x,y};
			cut(x,y);
		}
		else{
			read(x);
			link(q[x].u,q[x].v);
		}
	}
	return 0;
}

解:当边上有战争时,那就将这条边+1,查询x能否到y,就是查询x到y的路径权值和是否为0,树剖本来维护点,我们将每条边分给边上深度较大的一个点上,无论是修改还是查询操作,先全部算上,然后只要对x,y的最近公共祖先取消他的操作就可以了。


#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define SZ(a) int((a).size())
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int N=3e5+5; 
template <typename _Tp> il void read(_Tp&x) {
	char ch;bool flag=0;x=0;
	while(ch=getchar(),!isdigit(ch)) if(ch=='-')flag=1;
	while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
	if(flag) x=-x;
}
//il int Add(ll &x,ll y) {return x=x+y>=mod?x+y-mod:x+y;}
//il int Mul(ll &x,ll y) {return x=x*y>=mod?x*y%mod:x*y;}
vector<int> G[N]; 
int n,m,dep[N],sz[N],son[N],fa[N],id[N],bel[N],cnt;
il void dfs1(int x,int ff){
	fa[x]=ff,dep[x]=dep[ff]+1,sz[x]=1;
	int mx=-1;
	for(auto to:G[x]){
		if(to==ff) continue;
		dfs1(to,x);
		sz[x]+=sz[to];
		if(sz[to]>mx) son[x]=to,mx=sz[to];
	}
} 
il void dfs2(int x,int topx){
	id[x]=++cnt,bel[x]=topx;
	if(!son[x]) return ;
	dfs2(son[x],topx);
	for(auto to:G[x]){
		if(to==fa[x] || to==son[x]) continue;
		dfs2(to,to);
	} 
}
int lz[N<<2],s[N<<2],tsz[N<<2];
il void pushdown(int rt){
	if(lz[rt]){
		lz[rt<<1]+=lz[rt],lz[rt<<1|1]+=lz[rt];
		s[rt<<1]+=tsz[rt<<1]*lz[rt];
		s[rt<<1|1]+=tsz[rt<<1|1]*lz[rt];
		lz[rt]=0;
	}
} 
il void build(int l,int r,int rt){
	if(l==r){
		tsz[rt]=1;
		return;
	}
	build(l,mid,rt<<1);
	build(mid+1,r,rt<<1|1);
	tsz[rt]=tsz[rt<<1]+tsz[rt<<1|1];
}
il void update(int l,int r,int rt,int L,int R,int C){
	if(L<=l && r<=R){
		s[rt]+=C*tsz[rt],lz[rt]+=C;
		return;
	}
	pushdown(rt);
	if(L<=mid) update(l,mid,rt<<1,L,R,C);
	if(R>mid) update(mid+1,r,rt<<1|1,L,R,C);
	s[rt]=s[rt<<1]+s[rt<<1|1];
}
il int query(int l,int r,int rt,int L,int R){
	if(L<=l && r<=R){
		return s[rt];
	}
	int ans=0;
	pushdown(rt);
	if(L<=mid) ans+=query(l,mid,rt<<1,L,R);
	if(R>mid) ans+=query(mid+1,r,rt<<1|1,L,R);
	return ans;
} 
il void r_update(int x,int y,int w){
	while(bel[x]!=bel[y]){
		if(dep[bel[x]]<dep[bel[y]]) swap(x,y);
		update(1,n,1,id[bel[x]],id[x],w);
		x=fa[bel[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	update(1,n,1,id[x],id[y],w);
	update(1,n,1,id[x],id[x],-w);
}
il int r_ask(int x,int y){
	int res=0;
	while(bel[x]!=bel[y]){
		if(dep[bel[x]]<dep[bel[y]]) swap(x,y);
		res+=query(1,n,1,id[bel[x]],id[x]);
		x=fa[bel[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	res+=query(1,n,1,id[x],id[y]);
	res-=query(1,n,1,id[x],id[x]);
	return res;
}
char op[2];
struct node{
	int u,v;
}q[N];
int main(){
	read(n),read(m);
	int x,y,tot=0;
	for(int i=1;i<=n-1;++i){
		read(x),read(y);
		G[x].pb(y),G[y].pb(x);
	}
	dfs1(1,0);
	dfs2(1,1);
	build(1,n,1);
	while(m--){
		scanf("%s",op);
		if(op[0]=='Q'){
			read(x),read(y);
			if(r_ask(x,y)==0) printf("Yes\n");
			else printf("No\n");
		}
		else if(op[0]=='C'){
			read(x),read(y);
			q[++tot]={x,y};
			r_update(x,y,1);
		}
		else{
			read(x);
			r_update(q[x].u,q[x].v,-1);
		}
	}
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值