CodeChef VLB Vasya and Little Bear (树上莫队)

Codechef 一眼题题解合集 文章目录Sereja and EqualityDivision GameReach EquilibriumChef and SoccerPartition into PermutationsTravelling SaleschefKira Loves PalindromesPlaying with Numbers Sereja and Equality 简单组合数学+无脑前缀和优化dp计数。 fi... 阅读详情

题意:

       一棵树,每个点有一种颜色(10以内),一个价值,现在有Q次询问,每次询问在path(u,v)上,对于每种颜色算价值,价值是路径上相同颜色相邻的点的价值差的平方,如:u到v上颜色为1的点价值分别为a,b,c,则产生的价值是(a−b)2+(b−c)2(a−b)2+(b−c)2,注意,LCA(u,v)的颜色的价值不要

思路:

       树上莫队,那么首先对树分块,然后存询问,然后思考下怎么转移
       首先,L->L’和R-R’肯定是要分开维护的,所以使用双端队列维护,一个用front,一个用back,其次,路径顺序是对答案有影响的,那么比如我们在转移u->v的时候,要u->lca(u,v)->v,那么我们要先把路径保存下来,再进行处理

错误及反思:

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 100100;

stack<int> s; //分块时需要
int blocks,nowblo;//块大小,当前处于哪个块
int n,m;//节点数,问题数
int to[N][20],depth[N];//LCA
int block[N];
long long now,ans[N];
int head[N],tot;//链式前向星
bool vis[N];//标记路径

long long num[15];
int col[N],val[N];
deque<int> c[15];


struct EDGE{
    int to,nex;
}e[N*2];//双向边

void add(int x,int y){
    e[tot].nex=head[x];
    e[tot].to=y;
    head[x]=tot++;
}

struct Q{
    int l,r,id;
}q[N];

bool cmp(Q a,Q b){ //排序
    if(block[a.l]!=block[b.l])
        return block[a.l]<block[b.l];
    return block[a.r]<block[b.r];
}

void dfsblock(int now,int fa,int dep){ //树上分块
    int si=s.size();
    to[now][0]=fa;  depth[now]=dep;
    for(int i=head[now];i!=-1;i=e[i].nex){
        int x=e[i].to;
        if(x!=fa){
            dfsblock(x,now,dep+1);
            if(s.size()-si>=blocks){
                while(s.size()!=si){
                    block[s.top()]=nowblo;
                    s.pop();
                }
                nowblo++;
            }
        }
    }
    s.push(now);
}

void getlca(){   //预处理lca
    for(int i=1;i<=18;i++)
        for(int j=1;j<=n;j++)
            to[j][i]=to[to[j][i-1]][i-1];
}

int lca(int a,int b){ //得到lca
    if(depth[a]>depth[b]) swap(a,b);
    for(int i=18;i>=0;i--) //注意大小
        if(depth[to[b][i]]>=depth[a])
            b=to[b][i];
    if(a==b) return a;
    for(int i=18;i>=0;i--){ //注意大小
        if(to[a][i]!=to[b][i]){
            a=to[a][i];
            b=to[b][i];
        }
    }
    return to[a][0];
}

void change(int u,int v,int x){ //修改的时候将路径取反且不要动lca
    int ancs=lca(u,v);
    while(u!=ancs){
        if(!vis[u]){
            if(x){
                if(c[col[u]].size()>0){
                    now+=1ll*(val[c[col[u]].front()]-val[u])*(val[c[col[u]].front()]-val[u]);
                    num[col[u]]+=1ll*(val[c[col[u]].front()]-val[u])*(val[c[col[u]].front()]-val[u]);
                }
                c[col[u]].push_front(u);
            }
            else{
                if(c[col[u]].size()>0){
                    now+=1ll*(val[c[col[u]].back()]-val[u])*(val[c[col[u]].back()]-val[u]);
                    num[col[u]]+=1ll*(val[c[col[u]].back()]-val[u])*(val[c[col[u]].back()]-val[u]);
                }
                c[col[u]].push_back(u);
            }
        }
        else{
            if(x){
                if(c[col[u]].size()>=2){
                    int w=val[c[col[u]].front()];
                    c[col[u]].pop_front();
                    num[col[u]]-=1ll*(val[c[col[u]].front()]-w)*(val[c[col[u]].front()]-w);
                    now-=1ll*(val[c[col[u]].front()]-w)*(val[c[col[u]].front()]-w);
                }
                else
                    c[col[u]].pop_front();
            }
            else{
                if(c[col[u]].size()>=2){
                    int w=val[c[col[u]].back()];
                    c[col[u]].pop_back();
                    num[col[u]]-=1ll*(val[c[col[u]].back()]-w)*(val[c[col[u]].back()]-w);
                    now-=1ll*(val[c[col[u]].back()]-w)*(val[c[col[u]].back()]-w);
                }
                else
                    c[col[u]].pop_back();
            }
        }
        vis[u]=!vis[u];
        u=to[u][0];
    }
    vector<int> tmp;
    while(v!=ancs){
        tmp.push_back(v);
        v=to[v][0];
    }

    for(int i=tmp.size()-1;i>=0;i--){
        int k=tmp[i];
       // printf("%d %d\n",ancs,k);
        if(!vis[k]){
            if(x){
                if(c[col[k]].size()>0){
                    now+=1ll*(val[c[col[k]].front()]-val[k])*(val[c[col[k]].front()]-val[k]);
                    num[col[k]]+=1ll*(val[c[col[k]].front()]-val[k])*(val[c[col[k]].front()]-val[k]);
                }
                c[col[k]].push_front(k);
            }
            else{
                if(c[col[k]].size()>0){
                    now+=1ll*(val[c[col[k]].back()]-val[k])*(val[c[col[k]].back()]-val[k]);
                    num[col[k]]+=1ll*(val[c[col[k]].back()]-val[k])*(val[c[col[k]].back()]-val[k]);
                }
                c[col[k]].push_back(k);
            }
        }
        else{
            if(x){
                if(c[col[k]].size()>=2){
                    int w=val[c[col[k]].front()];
                    c[col[k]].pop_front();
                    num[col[k]]-=1ll*(val[c[col[k]].front()]-w)*(val[c[col[k]].front()]-w);
                    now-=1ll*(val[c[col[k]].front()]-w)*(val[c[col[k]].front()]-w);
                }
                else
                    c[col[k]].pop_front();
            }
            else{
                if(c[col[k]].size()>=2){
                    int w=val[c[col[k]].back()];
                    c[col[k]].pop_back();
                    num[col[k]]-=1ll*(val[c[col[k]].back()]-w)*(val[c[col[k]].back()]-w);
                    now-=1ll*(val[c[col[k]].back()]-w)*(val[c[col[k]].back()]-w);
                }
                else
                    c[col[k]].pop_back();
            }
        }
        vis[k]=!vis[k];
    }
}

void init(){
    memset(head,-1,sizeof(head));
    memset(vis,false,sizeof(vis));
    blocks=sqrt(n);
    nowblo=0;
    now=0; tot=0;
}

int main(){
    scanf("%d",&n);
    init(); //初始化
    for(int i=1;i<=n;i++) scanf("%d",&col[i]);
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);

    for(int i=1,u,v;i<n;i++){   //树的边
        scanf("%d%d",&u,&v);
        add(v,u); add(u,v);
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++){      //问题
        scanf("%d%d",&q[i].l,&q[i].r);
        q[i].id=i;
    }
    dfsblock(1,1,1);    //树上分块
    while(s.empty()){
        block[s.top()]=nowblo-1;
        s.pop();
    }
    getlca(); //预处理倍增lca
    sort(q+1,q+m+1,cmp); //问题排序
    for(int i=1,l=1,r=1;i<=m;i++){
        if(l!=q[i].l) change(l,q[i].l,0);  //左边节点

        if(r!=q[i].r) change(r,q[i].r,1); //右边节点
        int ancs=lca(q[i].l,q[i].r);
        ans[q[i].id]=now-num[col[ancs]];
        l=q[i].l; r=q[i].r;

       // printf("%lld %lld\n",num[col[ancs]],now);
    }
    for(int i=1;i<=m;i++)
        printf("%lld\n",ans[i]);
}
科技中介服务机构想要提升服务效率,需要哪些数智工具支持?.docx 科技中介服务机构想要提升服务效率,需要哪些数智工具支持? 立即下载

相关推荐

ArcGIS天地图矢量化秘籍:用重分类+ArcScan高效提取建筑轮廓线

本文详细介绍了利用ArcGIS重分类和ArcScan技术高效提取天地图建筑轮廓线的半自动化流程。通过动态中断值计算、多级重分类策略和ArcScan高级矢量化技巧,显著提升城市规划中的矢量化效率与精度,适用于中级GIS用户。

weixin_30879169的博客 475

Matlab 中的线性规划函数使用方法

线性规划 LP(Linear programming,线性规划)是一种优化方法,在优化问题中目标函数和约束函数均为向量变量的线性函数,LP问题可描述为: min  x s.t.               A·x b                  Aeq·x=beq                  vlb x vub 其中 ,b,beq均为向量,A,Aeq为矩阵,x为向量变量

FreshMan 7万+

青龙人形机器人硬件平台设计全解析:从构型到控制系统的实战指南

本文深度解析了青龙人形机器人硬件平台的设计全流程,从需求分析、构型设计到核心系统实现。文章详细阐述了其43个自由度的仿生构型、高动态性下肢设计、灵巧作业系统以及分布式控制架构,并探讨了旋转关节与直线关节等关键技术选型,为开发者提供了从理论到实践的完整硬件设计指南。

weixin_29248313的博客 383

Codechef MARCH14 GERALD07-莫队+并查集

传送门 这道题也是bzoj3514离线版 题意: 给你n个点,m条边,询问k个区间[L,R],求只保留[L,R]间的边,有多少个联通块。n,m,k<=200000Solution: 既然是离线那么显然可以搞事[滑稽],询问区间有什么暴力方法呢?莫队!因为在图上所以每次操作不是O(1)O(1),感觉似乎可以用并查集的样子呢,算一下复杂度为O(nn√α)O(n\sqrt n α)也是可以

Fizzmy的博客 622

最新Mamba环境配置教程:从CUDA到causal-conv1d的完整安装流程

本文提供最新Mamba环境配置教程,涵盖从CUDA到causal-conv1d的完整安装流程。针对深度学习领域的长序列处理需求,详细指导如何正确配置CUDA工具链、安装PyTorch及关键依赖causal-conv1d,解决常见报错问题,并验证mamba-ssm集成效果。

bush的博客 418

从零到一:RK3588嵌入式开发中的SDK与MPP集成实战解析

本文详细解析了RK3588嵌入式开发中SDK与MPP(Media Process Platform)的集成实战,涵盖开发环境构建、SDK架构解析、MPP集成关键技术点及常见问题诊断。通过Qt5.12.10交叉编译环境配置和硬件加速优化,帮助开发者高效完成嵌入式视觉项目开发,特别适合边缘计算应用场景。

weixin_29189381的博客 511

Chef and Queries (CodeChef - CHEFNUMK)莫队+离散化

题目链接:https://cn.vjudge.net/contest/321161#problem/C 题意:给你一个长度为n的数列 q此查询 每次查询给你三个数 l,r,k 区间为【l,r] 询问区间【l,r】内个数不超过k个的数量 比如说 数列 1 2 3 2 1 l=2,r=4 k=2 在【2,4】区间 内 2出现两次 3出现一次 出现次数均小于等于k 所以 均符合条件 答案是 ...

shoree的博客 295

Windows Server 搭建ftp服务

Windows Server 搭建ftp服务

ch258563的博客 1010

HDU 3333 Turing Tree(莫队+离散化)

题意:给你一个数列,每次询问一个子区间中不同数字的和思路:http://blog.youkuaiyun.com/roll_keyboard/article/details/78380548 ↑和这个题有点像,用莫队即可,在移动区间的时候,发现某个数字是1或者0的时候判断并且更新答案即可,但是直接莫队的复杂度是O(nn‾√logn)O(n\sqrt{n}\log n)会TLE,要提前离散一下,记录下每个数值的编

Roll_Keyboard的博客 512

手把手教你为ArduPilot添加自定义飞行模式:以自动巡检航线为例

本文详细介绍了如何为开源飞控ArduPilot添加自定义飞行模式,并以自动巡检航线为例,提供了从状态机设计、代码实现到地面站集成的完整开发指南。通过七步法手把手教学,帮助开发者深入理解飞控核心逻辑,实现无人机自主执行复杂巡检任务,满足行业应用定制需求。

weixin_29306875的博客 137

三电平逆变器LC滤波设计避坑指南:从SVPWM谐波到Simulink仿真验证

本文详细解析了三电平逆变器LC滤波设计中的关键问题,从SVPWM谐波特性到Simulink仿真验证,提供了800V/10kW系统的参数计算方法和优化技巧。通过实际案例和仿真配置示例,帮助工程师避免常见设计误区,提升电能质量和系统稳定性。

weixin_29261711的博客 173

Codeforces Round #442 (Div. 2) F. Ann and Books (莫队算法+离散化)

题意:给你一n个数字,其中有的是第一类,有的是第二类,接着是m个查询,问你某个区间内,连续的子区间的第一类的和减去第二类的和恰好为k的子区间一共多少个。思路:莫队算法及离散化。这个题不是一般的毒,卡logn。 首先对于这个题目,只查询不修改,很容易想到莫队算法。首先处理出前缀和,那么我val[i]-val[j]就能表示aj+1+aj+2+...+ai{a_{j+1}+{a_{j+2}+...+{a

Roll_Keyboard的博客 471

robot framework循环读取excel表操作

robot framework循环读取excel表操作 1、安装excellibrary,注意python3.7版本,需安装:robotframework-excel,robotframework-excellibrary-xwfintech 注意:网上有很多excel处理的,都是基于python2.7的,还有一些对python3以上都是修改包的方式,其实都不需要,在pip官网上有python3以上的excellibrary,名称是robotframework-excellib 2.0.0,但是该包关键字不

余墨的博客 1320

bzoj 3052/洛谷 P4074/uoj 58 [WC2013]糖果公园(树上带修莫队)

题意: UOJ地址 &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 洛谷地址 BZOJ因为版权挂了。。。 思路: &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 比较裸的一道树上带修莫队,我们只要维护一下某个糖出现了几次,然后更新答案即可 错误及反思: &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;n

Roll_Keyboard的博客 451

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

BZOJ 3289 Mato的文件管理(莫队+线段树/树状数组)

题意: 思路: 莫队+逆序数,思路还是很好想的,但是复杂度要纠结下。 对于[L,R]来说,向右边扩展,即变成了[L,R+1],就相当于只是在数组末端多了一个数,其他的操作也是同理,只要遵循,改变区间的时候,加上/减去比自己大的值即可 复杂度是莫队的o(nn‾√n\sqrt{n})乘以树状数组或者线段数查询的一个o(log(nn‾√)log(n\sqrt{n})) 错误及反思: 题目

Roll_Keyboard的博客 447

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

bzoj 2120 数颜色(可持久化莫队)

题意:思路:第一次写带修莫队,感觉还是比较简单的,相对于普通莫队,带修莫队主要是加了一个时间标志。大致思路就是,因为区间内的东西要修改,那就干脆继续暴力的修改,把[L,R]的转移,看成[L,R,T]的转移,依旧是利用排序进行优化,可以说带修莫队依旧是个暴力的优化。 不过,这题有一个疑点,就是在查看许多的博客里面,对于带修莫队,都说block为n23n^{\frac{2}{3}}时带修莫队速度达到最

Roll_Keyboard的博客 434

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Yandex.Algorithm 2011 Round 2 D - Powerful array (莫队算法)

题意:给你n个数,进行m个查询,每个查询有一个区间,如果1出现了cnt[1]次,2出现了cnt[2]次,3出现了cnt[3]次…..i出现cnt[i]次,那么就要求输出1∗cnt[1]2+2∗cnt[2]2+3∗cnt[3]2+...+i∗cnt[i]21*cnt[1]^2+2*cnt[2]^2+3*cnt[3]^2+...+i*cnt[i]^2思路:莫队裸题,用cnt记录下某个数字出现,这样就能o

Roll_Keyboard的博客 428

BZOJ 1878 [SDOI2009]HH的项链 (莫队算法)

题意:给你n个数字,然后查询某个区间有多少种数字思路:莫队裸题,用一个cnt维护区间数字的数量就能实现o(1)转移了错误及反思:代码:#include<bits/stdc++.h> using namespace std; const int maxn= 50000+10; const int maxm= 1000000+10; int pos[maxn]; int cnt[maxm]; int a

Roll_Keyboard的博客 402

NBUT 1457 Sona (莫队算法)

题意: 给你n个数字,q个询问,问[l,r]的价值,价值是每个数字出现次数的立方和 思路: 很基础的莫队,可是,这个oj有点毒 首先对于[l,r],我们转移为[l,r+1]的时候,只要加上去cnt[id[arr[r]]]3cnt[ id[ arr[r] ] ] ^3即可,其他的转移也很类似,也很好想,就不多说了。但是要注意这里需要离散化,并且不能直接用map,vector直接调用,要用

Roll_Keyboard的博客 400

SPOJ COT2 Count on a tree II (树上莫队)

题意: 思路: &nbsp;&nbsp;&nbsp;&nbsp; 树上分块方法&lt;-由这个题,我们可以得出一种分块方法,他能保证每个块中内部移动次数,同时也能保证块的大小 &nbsp;&nbsp;&nbsp;&nbsp; 这个是讲述怎么转移的因为转移的时候,lca非常麻烦,要各种分类讨论,这个博客告诉我们,只要不管lca进行转移,最后计算结果的时候临时加上lca即可 错误及反思: ...

Roll_Keyboard的博客 371

Codeforces Round #340 (Div. 2) E - XOR and Favorite Number (莫队算法)

题意:给你n个数,m个查询,每个查询问你一个区间里面,连续的数的异或值恰好为k的区间有多少个思路:莫队算法 如果我处理出前缀的异或,那么我ai^aj(i>j)的值,就是 aj+1{a_{j+1}} ^aj+1{a_{j+1}}^aj+3...aia_{j+3}...a_{i}的值。当我修改区间的时间,多一个值aia_{i},那么就相当于之前区间的答案加上cnt[k^aia_{i}],其他的也相似,

Roll_Keyboard的博客 356

bzoj 1086 王室联邦 (dfs,构造)

题意: 思路: &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 首先我们dfs,如果一个节点v的儿子u所在的子树大于等于B,那么就把这个子树当作一个省份,对于这种情况,省会是u,v其实都可以。如果一个儿子u所在的子树小于B,可以先暂存起来,继续遍历其他儿子,当暂存的数量大于等于B的时候,将暂存的都归为一个省,省会为v,因为会暂存的子树大小为B-1,所以这样产生的子树大小最大为2B-2,在...

Roll_Keyboard的博客 347

bzoj 4129 Haruna’s Breakfast(树上带修莫队)

题意: 思路: 树上带修莫队+块状数组,基本上还是很裸的 但是写起来很麻烦,看到好多人硬是压到90多行,真是跪了 总体思路就是,树上询问和修改还是莫队,但是在查询的时候,肯定不能O(n)地去询问,而线段树因为莫队每次移动区间都需要修改,会让总体复杂度多出一个logn,所以在查答案的时候用块状数组维护,这样由块状数组产生的复杂度是O(nn−−√)O(nn)O(n\sqrt{n}),不会使...

Roll_Keyboard的博客 317

Codeforces Round #466 (Div. 2) F. Machine Learning (带修莫队)

题意: &nbsp;&nbsp;&nbsp;&nbsp; 一个数组,问某个区间里面,第一个没出现的所有数出现次数的出现次数正整数 思路: &nbsp;&nbsp;&nbsp;&nbsp; 题意有点毒,第二次才读对。一读题就觉得,带修莫队就可以处理了,然后我们发现需要离散化,那么我们干脆在之前就把数字离散了,因为有修改,所以最多为2e5个数,这样就很好处理了。因为是出现次数的出现次数,所以最多...

Roll_Keyboard的博客 294

BZOJ 2038 [2009国家集训队]小Z的袜子(hose) (莫队算法)

题意:给你n个数字,要进行m次查询,每次查询中,问l-r中,任意选两个数字且这两个数字相同的概率思路:第一次写莫队算法,莫队算法是一种暴力解决区间问题的一种算法。只有在区间没修改或修改的很少才能使用。 莫队算法其实很简单很暴力。如果我们知道了[l,r]区间的答案,那么我们就能o(1)地知道[l-1,r],[l,r-1],[l+1,r],[l,r+1]。这样的话,要知道[l’,r’]的答案,只要用一

Roll_Keyboard的博客 284
上一篇: 牛客多校训练(第一场)H-Longest Path(点分治+李超树)
下一篇: HDU 4776 (字典树)
Roll_Keyboard
博客等级 码龄9年 10粉丝 128原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值