首页 > 其他分享 >#根号分治,分块,dfs序#洛谷 7710 [Ynoi2077] stdmxeypz

#根号分治,分块,dfs序#洛谷 7710 [Ynoi2077] stdmxeypz

时间:2024-02-22 14:12:22浏览次数:29  
标签:7710 洛谷 int siz pos dfs dfn ans 根号

题目传送门


分析

首先把距离变成深度,用dfs序转成区间问题,考虑分块,散块直接改

问题是整块,如果模数比较大,可以以深度为第一维下标差分标记,这样查询时就可以前缀和知道答案

如果模数比较小,那么给该块打标记,查询时枚举模数即可,然后块长取1000,模数阈值取300,就能尽量减少时间


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=300011,M=311; struct node{int y,next;}e[N];
int dfn[N],nfd[N],siz[N],tot,n,Q,bl,Bl,pos[N],a[N],as[N],dep[N],S[N][M],s[M][M][M];
int iut(){
    int ans=0; char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=ans*10+c-48,c=getchar();
    return ans;
}
void print(int ans){
    if (ans>9) print(ans/10);
    putchar(ans%10+48);
}
void dfs(int x){
    dfn[x]=++tot,nfd[tot]=x,siz[x]=1;
    for (int i=as[x];i;i=e[i].next){
        dep[e[i].y]=dep[x]+1;
        dfs(e[i].y),siz[x]+=siz[e[i].y];
    }
}
void update(int x,int p,int y,int z){
    int l=dfn[x],r=dfn[x]+siz[x]-1;
    if (pos[l]==pos[r]){
        for (int i=l;i<=r;++i)
            if (dep[nfd[i]]%p==y) a[nfd[i]]+=z;
    }else{
        for (int i=l;i<=pos[l]*bl;++i)
            if (dep[nfd[i]]%p==y) a[nfd[i]]+=z;
        if (p<=Bl) for (int i=pos[l]+1;i<pos[r];++i) s[i][p][y]+=z;
            else for (int i=y;i<=n;i+=p) S[i][pos[l]+1]+=z,S[i][pos[r]]-=z;
        for (int i=r;i>(pos[r]-1)*bl;--i)
            if (dep[nfd[i]]%p==y) a[nfd[i]]+=z;
    }
}
int main(){
    n=iut(),Q=iut(),bl=1000,Bl=300;
    for (int i=1;i<=n;++i) pos[i]=(i-1)/bl+1;
    for (int i=2;i<=n;++i){
        int x=iut();
        e[i]=(node){i,as[x]},as[x]=i;
    }
    dfs(1);
    for (int i=1;i<=Q;++i)
    if (iut()==2){
        int x=iut(),ans=a[x];
        for (int i=1;i<=Bl;++i) ans+=s[pos[dfn[x]]][i][dep[x]%i];
        for (int i=1;i<=pos[dfn[x]];++i) ans+=S[dep[x]][i];
        print(ans),putchar(10);
    }else{
        int x=iut(),p=iut(),y=iut(),z=iut();
        update(x,p,(dep[x]+y)%p,z);
    }
    return 0;
}

标签:7710,洛谷,int,siz,pos,dfs,dfn,ans,根号
From: https://www.cnblogs.com/Spare-No-Effort/p/18027203

相关文章

  • 洛谷 【数据结构1-1】线性表
    P3156【深基15.例1】询问学号-洛谷|计算机科学教育新生态(luogu.com.cn)#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;constintINF=0x3f3f3f3f;intn,m;map<int,int>mp;signedmain(){ios::sync_with_stdio(false);cin.tie(0);c......
  • 洛谷题单指南-递推与递归-P1498 南蛮图腾
    原题链接:https://www.luogu.com.cn/problem/P1498题意解读:观察样例,可以发现,当n=1时,得到最基础的图案:/\/__\当n=2时,将基础图案向下复制两个,并排,然后将之前的图案移到居中的位置/\/__\/\/\/__\/__\当n=3时,再将n=2时的图案向下复制两个,并排,然后将之前的图......
  • [洛谷P3503][POI2010][BZOI2086]Blocks
    先看数据范围,n≤1e7,k≤1e9,暴力显然行不通,只能考虑单调栈;首先题目中说每一个数都要大于k,那么我们可以在初始化时就将每一个数都减去k,将问题转化为从正数中取出数加到负数里;然后维护一个前缀和,来判断一个区间是否符合要求;显然,当sum[j]-sum[i]≥0时,区间[i+1,j]符合题意,......
  • 洛谷 P6610 [Code+#7] 同余方程
    题目描述给出若干组正整数\(p\)和\(x\),求方程\(a^2+b^2\equivx\pmodp\)关于\(a\)和\(b\)在模\(p\)意义下解的组数,其中\(p\)是奇数,且不包含平方因子题解来整一个更注重于观察结构而不是计算的题解(首先使用CRT将问题转化为模奇质数的结果相乘是显然的......
  • #根号分治,分块#洛谷 5309 [Ynoi2011] 初始化
    题目传送门分析如果\(x\)比较大那么可以暴力修改,\(x\)比较小的话可以用数组打标记查询的时候对于暴力修改的部分可以分块,暴力修改的同时需要给块打标记如果\(x\)比较小的情况,一段区间相当于是中间很多段周期加上前后缀(当然可以直接区间减但是我被卡常了)我调的块长是160......
  • 洛谷P4447题解
    md这篇反正不交题解的,随便写,不管它格式题意简化下,给你N个数,求出连续值分组人数最小的那组的人数最大值。这个题目还挺经典的,原本23年8月份过了到现在来又不会了(划掉,bushi对于这种,很容易想到的是输入,之后排序,然后分组这种模板就不多说了,就在我24年2月份重温这道题再打一遍代码......
  • 洛谷题单指南-递推与递归-P1228 地毯填补问题
    原题链接:https://www.luogu.com.cn/problem/P1228题意解读:用4种毯子铺满2^k*2^k的区域,留出一个公主位置,输出所有毯子拐角的坐标以及哪种毯子,看起来有点无从下手,可以从k=1,k=2,k=3入手去依次考虑,找到规律,用分治法解决。解题思路:1、当k=1时,即2*2的区域,对于任意一个位置是公主,都......
  • 洛谷题单指南-递推与递归-P1010 [NOIP1998 普及组] 幂次方
    原题链接:https://www.luogu.com.cn/problem/P1010题意解读:输出一个正整数的2的幂次方表示,需要用到二进制数学知识,将整数拆解成2的次幂之和,幂次方也要进行拆解,因此容易想到通过递归处理。解题思路:先看样例,给定整数137,要拆解成2的幂次方之和,先考虑i使得刚好137>=2^i时,i取7,因此2......
  • 洛谷P1160
    队列安排题目描述一个学校里老师要将班上\(N\)个同学排成一列,同学被编号为\(1\simN\),他采取如下的方法:先将\(1\)号同学安排进队列,这时队列中只有他一个人;\(2\simN\)号同学依次入列,编号为\(i\)的同学入列方式为:老师指定编号为\(i\)的同学站在编号为\(1\sim(i-......
  • 洛谷P1996
    约瑟夫问题题目描述\(n\)个人围成一圈,从第一个人开始报数,数到\(m\)的人出列,再由下一个人重新从\(1\)开始报数,数到\(m\)的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。注意:本题和《深入浅出-基础篇》上例题的表述稍有不同。书上表述是给出淘汰\(n-1\)......