首页 技术 正文
技术 2022年11月17日
0 收藏 692 点赞 2,140 浏览 2676 个字

终于做了一道不是一眼出思路的代码题(⊙o⊙)

之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱)

实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开线段树的时候记录一下就好了

事实上我开了一个node,并且写了一个mix还是大大减小了代码量(对于我这种手残党来说同时大大减小了错误率)

由于前几题做的都是树链剖分,并没有在这一方面出问题,然而线段树还是不熟练,刚写完的时候居然忘记down了(mdzz)

对wa了N遍的总结:

由于是树上两个点间的路径,既有向上的路也有向下的路,然而树剖下来的结果是按深度排的,所以在链上跑的时候会发现一段链的左右(l和r)有时候是相反的,在合并几条链的时候一定要注意(事实证明我这么多遍wa全是因为没有翻转链)

对这一类问题的总结:

对于每一段都考虑有用(会对周围产生影响)的信息,在染色段数中就是两端(因为可能和隔壁合并)

 //加了一大堆斜杠的是第一遍写之后补的
#include <cstdio>
#include <iostream>
#define mid (l+r)/2
using namespace std;
int m=,N=,n,M,p,q,o;
int to[],nex[],fir[],son[],bro[],co[];
int size[],l[],pos[],fa[],h[],top[];
struct node{int s,l,r;bool b;}t[],ans[];
inline void add(int x,int y){to[++m]=y;nex[m]=fir[x];fir[x]=m;}
inline node mix(node x,node y){return (node){x.s+y.s-(x.r==y.l),x.l,y.r,};}
int build(int now,int fat)
{
size[now]=;fa[now]=fat;h[now]=h[fat]+;
for(int i=fir[now];i;i=nex[i])
if(to[i]!=fat)
size[now]+=build(to[i],now),bro[to[i]]=son[now],son[now]=to[i];
return size[now];
}
void pou(int now,int to)
{
l[++N]=now;pos[now]=N;top[now]=to;
int max=son[now];
if(!max) return;
for(int i=bro[max];i;i=bro[i])
if(size[i]>size[max]) max=i;
pou(max,to);
for(int i=son[now];i;i=bro[i])
if(i!=max) pou(i,i);
}
void down(int now)////////////////////////////
{
if(t[now].b)
{
t[now].b=;t[now*].b=t[now*+].b=;
t[now*].s=t[now*+].s=;
t[now*].l=t[now*].r=t[now*+].l=t[now*+].r=t[now].l;
}
}
void work(int now,int l,int r,int x,int y,int z)
{
if(l==x && r==y)
{ t[now]=(node){,z,z,}; return;}
down(now);
if(x<=mid)
work(now*,l,mid,x,min(y,mid),z);
if(y>mid)
work(now*+,mid+,r,max(x,mid+),y,z);
t[now]=mix(t[now*],t[now*+]);
}
node que(int now,int l,int r,int x,int y)
{
if(l==x && r==y)
return t[now];
down(now);
if(y<=mid) return que(now*,l,mid,x,y);
if(x>mid) return que(now*+,mid+,r,x,y);
return mix(que(now*,l,mid,x,mid),que(now*+,mid+,r,mid+,y));
}
void solve(int x,int y,int z)
{
bool b=;ans[]=ans[]=(node){,-,-,};
while(top[x]!=top[y])
{
if(h[top[x]]<h[top[y]]) swap(x,y),b=!b;
if(z==-)
{
node tem=que(,,n,pos[top[x]],pos[x]);
if(!b) swap(tem.l,tem.r);///////////////////////////////
if(ans[b].s==) ans[b]=tem;
else
ans[b]=b?mix(tem,ans[b]):mix(ans[b],tem);
}
else
work(,,n,pos[top[x]],pos[x],z);
x=fa[top[x]];
}
if(h[x]>h[y]) swap(x,y),b=!b;//////////////////
if(z==-)
{
node tem=que(,,n,pos[x],pos[y]);b=!b;////////////////
if(!b) swap(tem.l,tem.r);
if(ans[b].s==) ans[b]=tem;
else
ans[b]=b?mix(tem,ans[b]):mix(ans[b],tem);
printf("%d\n",mix(ans[],ans[]).s);
}
else
work(,,n,pos[x],pos[y],z);
}
int main()
{
scanf("%d%d",&n,&M);
for(int i=;i<=n;i++)
scanf("%d",&co[i]);
for(int i=;i<n;i++)
scanf("%d%d",&p,&q),add(p,q),add(q,p);
build(,);
pou(,);
for(int i=;i<=n;i++)
work(,,n,pos[i],pos[i],co[i]);
for(int i=;i<=M;i++)
{
char ch=getchar();
while(ch!='C' && ch!='Q') ch=getchar();
if(ch=='C')
scanf("%d%d%d",&p,&q,&o),solve(p,q,o);
else
scanf("%d%d",&p,&q),solve(p,q,-);
}
return ;
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,082
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,556
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,405
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,179
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,815
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,898