题面

强行把序列问题通过树剖套在树上。。。算了算是回顾了一下树剖的思想=。=

每次树上跳的时候注意跳的同时维护当前拼出来的左右两条链的靠上的端点,然后拼起来的时候讨论一下拼接点,最后一下左右两边的端点都要考虑

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
struct a
{
int cnt;
int lc,rc;
};
int num[N],nmb[N],val[*N],lcol[*N],rcol[*N],laz[*N];
int siz[N],dep[N],anc[N],imp[N],top[N],dfn[N];
int p[N],noww[*N],goal[*N];
int n,m,t1,t2,t3,cnt,tot;
char rd[];
void link(int f,int t)
{
noww[++cnt]=p[f];
goal[cnt]=t,p[f]=cnt;
}
void DFS(int nde,int fth,int dth)
{
int tmp=;
siz[nde]=,anc[nde]=fth,dep[nde]=dth;
for(int i=p[nde];i;i=noww[i])
if(goal[i]!=fth)
{
DFS(goal[i],nde,dth+);
siz[nde]+=siz[goal[i]];
if(siz[goal[i]]>tmp)
tmp=siz[goal[i]],imp[nde]=goal[i];
}
}
void MARK(int nde,int tpp)
{
dfn[nde]=++tot,nmb[tot]=num[nde],top[nde]=tpp;
if(imp[nde])
{
MARK(imp[nde],tpp);
for(int i=p[nde];i;i=noww[i])
if(goal[i]!=anc[nde]&&goal[i]!=imp[nde])
MARK(goal[i],goal[i]);
}
}
void pushup(int nde)
{
int ls=*nde,rs=*nde+;
lcol[nde]=lcol[ls],rcol[nde]=rcol[rs];
val[nde]=val[ls]+val[rs]-(rcol[ls]==lcol[rs]);
}
void create(int nde,int l,int r)
{
if(l==r)
val[nde]=,lcol[nde]=rcol[nde]=nmb[l];
else
{
int mid=(l+r)/,ls=*nde,rs=*nde+;
create(ls,l,mid),create(rs,mid+,r);
pushup(nde);
}
}
void release(int nde,int l,int r)
{
if(laz[nde])
{
int ls=*nde,rs=*nde+;
laz[ls]=lcol[ls]=rcol[ls]=laz[nde];
laz[rs]=lcol[rs]=rcol[rs]=laz[nde];
val[ls]=val[rs]=; laz[nde]=;
}
}
void change(int nde,int l,int r,int nl,int nr,int task)
{
if(l>nr||r<nl)
return ;
else if(l>=nl&&r<=nr)
val[nde]=,lcol[nde]=rcol[nde]=laz[nde]=task;
else
{
int mid=(l+r)/,ls=*nde,rs=*nde+; release(nde,l,r);
change(ls,l,mid,nl,nr,task),change(rs,mid+,r,nl,nr,task);
pushup(nde);
}
}
a query(int nde,int l,int r,int nl,int nr)
{
if(l>=nl&&r<=nr)
return (a){val[nde],lcol[nde],rcol[nde]};
else
{
int mid=(l+r)/,ls=*nde,rs=*nde+; release(nde,l,r);
if(nr<=mid) return query(ls,l,mid,nl,nr);
if(nl>mid) return query(rs,mid+,r,nl,nr);
a r1=query(ls,l,mid,nl,nr),r2=query(rs,mid+,r,nl,nr),ret;
ret.lc=r1.lc,ret.rc=r2.rc,ret.cnt=r1.cnt+r2.cnt-(r1.rc==r2.lc);
return ret;
}
}
void path_change(int x,int y,int v)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
change(,,n,dfn[top[x]],dfn[x],v); x=anc[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
change(,,n,dfn[x],dfn[y],v); return ;
}
int path_query(int x,int y)
{
int rt=,ll=-,rr=-;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y),swap(ll,rr);
a ret=query(,,n,dfn[top[x]],dfn[x]); x=anc[top[x]];
rt+=ret.cnt-(ll==ret.rc); ll=ret.lc;
}
if(dep[x]>dep[y]) swap(x,y),swap(ll,rr);
a ret=query(,,n,dfn[x],dfn[y]); rt+=ret.cnt-(ll==ret.lc)-(rr==ret.rc);
return rt;
}
int main ()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d",&num[i]);
for(int i=;i<n;i++)
scanf("%d%d",&t1,&t2),link(t1,t2),link(t2,t1);
DFS(,,); MARK(,); create(,,n);
while(m--)
{
scanf("%s",rd);
if(rd[]=='C')
scanf("%d%d%d",&t1,&t2,&t3),path_change(t1,t2,t3);
else
scanf("%d%d",&t1,&t2),printf("%d\n",path_query(t1,t2));
}
return ;
}

解题: SDOI 2011 染色的更多相关文章

  1. [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】

    题目链接:BZOJ - 2243 题目分析 树链剖分...写了200+行...Debug了整整一天+... 静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了. 提交之后全 WA . ————— ...

  2. BZOJ 2243 SDOI 2011染色

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 算法讨论: 树链剖分把树放到线段树上.然后线段树的每个节点要维护的东西有左端点的颜色 ...

  3. [SDOI 2011]染色

    Description 题库链接 给定一棵有 \(n\) 个节点的无根树和 \(m\) 个操作,操作有 \(2\) 类: 将节点 \(a\) 到节点 \(b\) 路径上所有点都染成颜色 \(c\) : ...

  4. 解题:SDOI 2011 消耗战

    题面 本身求答案是简单的树上DP,只需要求出根到每个点路径上的最小值,然后考虑割连父亲的边还是割所有儿子即可,但是每次都这样做一次显然不能通过,考虑优化 用虚树来优化:虚树是针对树上一些点建出来的一棵 ...

  5. 【SDOI 2011】染色

    [题目链接] 点击打开链接 [算法] 树链剖分 [代码] 本题,笔者求最近公共祖先并没有用树链剖分“往上跳”的方式,而是用倍增法.笔者认为这样比较好写,代码可读性 比较高 此外,笔者的线段树并没有用懒 ...

  6. 【codevs 1565】【SDOI 2011】计算器 快速幂+拓展欧几里得+BSGS算法

    BSGS算法是meet in the middle思想的一种应用,参考Yveh的博客我学会了BSGS的模版和hash表模板,,, 现在才会hash是不是太弱了,,, #include<cmath ...

  7. [bzoj2286][Sdoi 2011]消耗战

    [bzoj2286]消耗战 标签: 虚树 DP 题目链接 题解 很容易找出\(O(mn)\)的做法. 只需要每次都dp一遍. 但是m和n是同阶的,所以这样肯定会T的. 注意到dp的时候有很多节点是不需 ...

  8. [SDOI 2011]黑白棋

    Description 题库链接 给出一个 \(1\times n\) 的棋盘,棋盘上有 \(k\) 个棋子,一半是黑色,一半是白色.最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小 \( ...

  9. [SDOI 2011]消耗战

    Description 题库链接 给你一棵 \(n\) 个节点根节点为 \(1\) 的有根树,有边权. \(m\) 次询问,每次给出 \(k_i\) 个关键点.询问切断一些边,使这些点到根节点不连通, ...

随机推荐

  1. Hyperledger Fabric 1.0 从零开始(一)

    在HyperLedger/Fabric发布0.6的时候,公司就已经安排了一个团队研究这一块,后来也请IBM的专家组过来培训了一批人,不幸的是,这批人后来全走了,然后1.0就发布了.自从2017年7月H ...

  2. go 运行项目

    此时运行项目,不能像之前简单的使用go run main.go,因为包main包含main.go和router.go的文件,因此需要运行go run *.go命令编译运行.如果是最终编译二进制项目,则 ...

  3. tac命令详解

    基础命令学习目录首页 原文链接:http://blog.chinaunix.net/uid-128922-id-289974.html 有许多命令都可以查看文件,不同的命令有不同的优点,可以针对不同的 ...

  4. route命令详情

    基础命令学习目录首页 原文链接:https://www.cnblogs.com/lpfuture/p/5857738.html 考试题一:linux下如何添加路由(百度面试题) 以上是原题,老男孩老师 ...

  5. [译文]c#扩展方法(Extension Method In C#)

    原文链接: https://www.codeproject.com/Tips/709310/Extension-Method-In-Csharp 介绍 扩展方法是C# 3.0引入的新特性.扩展方法使你 ...

  6. jdk8 Optional使用详解

    思考: 调用一个方法得到了返回值却不能直接将返回值作为参数去调用别的方法. 原来解决方案: 我们首先要判断这个返回值是否为null,只有在非空的前提下才能将其作为其他方法的参数.这正是一些类似Guav ...

  7. iOS开发学习-放大长图与屏幕等宽

    /* 需要得到一个图片的放大比例,这个比例就是屏幕的宽度与图片真实宽度的比值 */ CGFloat newZoomScale = LZ_SCREEN_WIDTH / [_photoImageView. ...

  8. ubuntu中启动VIM,以及学习VIM

    启动VIM:首先打开终端,然后输入vi回车,然后输入i或者a,进入. 学习VIM:首先打开终端,然后输入vimtutor回车,然后进入教程学习.

  9. 个人作业 - Week2 - 代码复审

    代码复审Check List 概要部分 代码能符合需求和规格说明么? 能完成1~1000000个数独的求解与生成,并能处理异常输入,满足需求. 代码设计是否有周全的考虑? 为输入单独开设了一个输入检测 ...

  10. Beta阶段——第四篇 Scrum 冲刺博客

    i. 提供当天站立式会议照片一张: ii. 每个人的工作 (有work item 的ID) (1) 昨天已完成的工作: 充值与账单的数据库操作结合,实现余额功能 (2) 今天计划完成的工作: 用户权限 ...