BZOJ 3083 树链剖分+倍增+线段树
思路:
先随便选个点 链剖+线段树
1操作 就直接改root变量的值
2操作 线段树上改
3操作
分成三种情况
1.new root = xx 整个子树的min就是ans
2. lca(new root,xx) !=xx query 一下 当前的标号 和当前的标号+size(链剖不就是个特殊的dfs序嘛)
3. lca(new root,xx) =xx 找一下root在xx的哪个子树里 这个子树的补集就是解了
好多题解写得是有问题的
他们找root在xx的哪个子树里 这个操作是暴力找的 会被菊花图卡
(所以我就又写了个倍增)
后附 对拍程序 (这玩意儿一遍AC真是幻想 啊……)
//By SiriusRen33333333333333
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 222222
int n,m,op,xx,yy,zz,v[N],next[N],first[N],tot,wei[N],tree[N*8],lazy[N*8];
int size[N],son[N],fa[N],deep[N],top[N],change[N],cnt,root,f[N][20],rev[N];
void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
void dfs(int x){
size[x]=1;
for(int i=1;i<=19;i++)if((1<<i)<=deep[x])f[x][i]=f[f[x][i-1]][i-1];else break;
for(int i=first[x];~i;i=next[i])if(v[i]!=fa[x]){
fa[v[i]]=f[v[i]][0]=x,deep[v[i]]=deep[x]+1,dfs(v[i]);
size[x]+=size[v[i]];
if(size[son[x]]<size[v[i]])son[x]=v[i];
}
}
void dfs2(int x,int tp){
change[x]=++cnt,rev[cnt]=x,top[x]=tp;
if(son[x])dfs2(son[x],tp);
for(int i=first[x];~i;i=next[i])
if(v[i]!=fa[x]&&v[i]!=son[x])
dfs2(v[i],v[i]);
}
void push_down(int pos){lazy[pos<<1]=lazy[pos<<1|1]=tree[pos<<1]=tree[pos<<1|1]=lazy[pos];lazy[pos]=-1;}
void build(int l,int r,int pos){
if(l==r){tree[pos]=wei[rev[l]];return;}
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
build(l,mid,lson),build(mid+1,r,rson);
tree[pos]=min(tree[lson],tree[rson]);
}
void insert(int l,int r,int pos,int L,int R,int val){
if(l>=L&&r<=R){tree[pos]=lazy[pos]=val;return;}
if(~lazy[pos])push_down(pos);
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<L)insert(mid+1,r,rson,L,R,val);
else if(mid>=R)insert(l,mid,lson,L,R,val);
else insert(l,mid,lson,L,R,val),insert(mid+1,r,rson,L,R,val);
tree[pos]=min(tree[lson],tree[rson]);
}
int query(int l,int r,int pos,int L,int R){
if(l>=L&&r<=R)return tree[pos];
if(~lazy[pos])push_down(pos);
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<L)return query(mid+1,r,rson,L,R);
else if(mid>=R)return query(l,mid,lson,L,R);
else return min(query(l,mid,lson,L,R),query(mid+1,r,rson,L,R));
}
void Change(int x,int y,int val){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(deep[fx]<deep[fy])swap(x,y),swap(fx,fy);
insert(1,n,1,change[fx],change[x],val);
x=fa[fx],fx=top[x];
}if(deep[x]>deep[y])swap(x,y);
insert(1,n,1,change[x],change[y],val);
}
int LCA(int x,int y){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(deep[fx]<deep[fy])swap(x,y),swap(fx,fy);
x=fa[fx],fx=top[x];
}return deep[x]>deep[y]?y:x;
}
int main(){
memset(first,-1,sizeof(first)),memset(lazy,-1,sizeof(lazy));
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)scanf("%d%d",&xx,&yy),add(xx,yy),add(yy,xx);
for(int i=1;i<=n;i++)scanf("%d",&wei[i]);
dfs(1),dfs2(1,1),build(1,n,1);
scanf("%d",&root);
for(int i=1;i<=m;i++){
scanf("%d%d",&op,&xx);
if(op==1)root=xx;
else if(op==2)scanf("%d%d",&yy,&zz),Change(xx,yy,zz);
else{
if(root==xx){printf("%d\n",tree[1]);continue;}
int lca=LCA(xx,root);
if(xx!=lca)printf("%d\n",query(1,n,1,change[xx],change[xx]+size[xx]-1));
else{
int tmp=deep[root]-deep[xx]-1,ans=0x3f3f3f3f;yy=root;
for(int i=0;i<=19;i++)if((1<<i)&tmp)yy=f[yy][i];
if(change[yy]>1)ans=query(1,n,1,1,change[yy]-1);
if(change[yy]+size[yy]<=n)ans=min(ans,query(1,n,1,change[yy]+size[yy],n));
printf("%d\n",ans);
}
}
}
}
maker
//By SiriusRen
#include <ctime>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n=100000,m=100000,seed;
int main(){
freopen("seed.txt","r",stdin);
scanf("%d",&seed);
srand(seed+time(0));rand();rand();rand();rand();rand();rand();rand();rand();
freopen("seed.txt","w",stdout);
printf("%d\n",seed);
freopen("in.txt","w",stdout);
printf("%d %d\n",n,m);
for(int i=2;i<=n;i++)printf("%d %d\n",rand()%(i-1)+1,i);
for(int i=1;i<=n;i++)printf("%d ",rand()+1);
printf("\n%d\n",rand()%n+1);
for(int i=1;i<=m;i++){
int temp=rand();
if(temp%3==0)printf("1 %d\n",rand()%n+1);
else if(temp%3==1)printf("2 %d %d %d\n",rand()%n+1,rand()%n+1,rand()+1);
else printf("3 %d\n",rand()%n+1);
}
}
对拍:
//By SiriusRen
#include <ctime>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int cases;
int main(){
while(1){
printf("Case %d now~~~\n",++cases);
system("mk.exe");
int lasttime=clock();
system("mine.exe<in.txt>out1.txt");
printf("mine time=%ld\n",clock()-lasttime);
lasttime=clock();
system("sol.exe<in.txt>out2.txt");
printf("solution time=%ld\n",clock()-lasttime);
lasttime=clock();
if(system("fc out1.txt out2.txt")){
puts("Wrong Answer~~~");
while(1);
}
}
}
BZOJ 3083 树链剖分+倍增+线段树的更多相关文章
- HDU3710 Battle over Cities(最小生成树+树链剖分+倍增+线段树)
Battle over Cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- bzoj 4034 [HAOI2015] T2(树链剖分,线段树)
4034: [HAOI2015]T2 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1536 Solved: 508[Submit][Status] ...
- bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 10677 Solved: 4313[Submit ...
- bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1272 Solved: 451[Submit][Status ...
- bzoj 2243 [SDOI2011]染色(树链剖分,线段树)
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4637 Solved: 1726[Submit][Status ...
- 【BZOJ5507】[GXOI/GZOI2019]旧词(树链剖分,线段树)
[BZOJ5507][GXOI/GZOI2019]旧词(树链剖分,线段树) 题面 BZOJ 洛谷 题解 如果\(k=1\)就是链并裸题了... 其实\(k>1\)发现还是可以用类似链并的思想,这 ...
- poj 3237 Tree(树链剖分,线段树)
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 7268 Accepted: 1969 Description ...
- HDU 4366 Successor(树链剖分+zkw线段树+扫描线)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4366 [题目大意] 有一个公司,每个员工都有一个上司,所有的人呈树状关系,现在给出每个人的忠诚值和 ...
- 【BZOJ3531】旅行(树链剖分,线段树)
[BZOJ3531]旅行(树链剖分,线段树) 题面 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教 ...
随机推荐
- Java 实现适配器(Adapter)模式
平时我们会常常碰到这种情况,有了两个现成的类,它们之间没有什么联系.可是我们如今既想用当中一个类的方法.同一时候也想用另外一个类的方法.有一个解决方法是.改动它们各自的接口.可是这是我们最不愿意看到的 ...
- Java面试中常问的数据库方面问题
MySQL 为什么用自增列作为主键 如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引.如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作 ...
- PHP第八课 字符串拆分经常使用函数
课程概要: 通过这节课可以对字符串进行主要的操作. 字符串知识点: 1.字符串的处理介绍 2.经常使用的字符串输出函数 3.经常使用的字符串格式化函数 4.字符串比較函数 5.正則表達式在字符串中的应 ...
- chrome的F12的inspect使用
chrome中查看cookie https://stackoverflow.com/questions/10014996/how-do-you-check-cookies-using-chrome T ...
- mysql读写分离原理及配置
1 复制概述 Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重 ...
- Gram矩阵 迁移学习 one-shot 之类
格拉姆矩阵是由内积空间中的向量两两内积而得.格拉姆矩阵在向量为随机的情况下也是协方差矩阵.每个数字都来自于一个特定滤波器在特定位置的卷积,因此每个数字代表一个特征的强度,而Gram计算的实际上是两两特 ...
- 51nod 1267 4个数和为0 思路:哈希map+避免重复的点
题目: 总结大佬们的思路: 思路1:所有数两两求和,存入map中,每次判断有没有相反数被标记过. 思路2:对所有数排序,排完所有数两两求和,结果正好是排好序的.然后扫一遍,二分查找看之前有没有相反数存 ...
- PKI和加密,散列算法
Day 11-PKI和加密,散列算法 PKI(Public Key Infrastructure公钥基础设施) 1 PKI(Public Key Infrastructure公钥基础设施)回顾学习 - ...
- ubuntu 装tensorflow出现 conda install ERROR missing write permission错误
通过搜索tensorflow然后运行,例如:$ conda install --channel https://conda.anaconda.org/jjh_cio_testing tensorflo ...
- C语言编译和链接
编译链接是使用高级语言编程所必须的操作,一个源程序只有经过编译.链接操作以后才可以变成计算机可以理解并执行的二进制可执行文件. 编译是指根据用户写的源程序代码,经过词法和语法分析,将高级语言编写的代码 ...