BZOJ 4129 Haruna’s Breakfast 带修改树上莫队+分块

题目大意:给定一棵树,每个点有一个非负点权,支持下列操作

1.修改某个点的点权

2.查询某条链上的mex

考虑链上不带修改的版本,我们可以用莫队+分块来搞(链接戳这里)

现在到了树上带修改,果断糖果公园

本来抱着逗比的心态写了一发结果1.4s过了

跟糖果公园的80s完全不成正比啊0.0

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 50500
#define B 1500
using namespace std;

struct abcd{
    int to,next;
}table[M<<1];
int head[M],tot;

int n,m,b1,b2,q,c,L=1,R=1,t;
int fa[M],ancestor[M][16],dpt[M];
int a[M],cnt[M],block[M];
bool v[M];
int belong[M],_cnt;

struct Modifiction{
    int x,from,to,t;
}modifictions[M];

struct Query{
    int x,y,t,ans;
    bool operator < (const Query &q) const
    {
        if( belong[x] != belong[q.x] )
            return belong[x] < belong[q.x];
        if( belong[y] != belong[q.y] )
            return belong[y] < belong[q.y];
        return t < q.t ;
    }
}queries[M];

bool Compare(const Query &q1,const Query &q2)
{
    return q1.t < q2.t ;
}

void Add(int x,int y)
{
    table[++tot].to=y;
    table[tot].next=head[x];
    head[x]=tot;
}

void DFS(int x)
{
    static int stack[M],top;
    int i,bottom=top;
    dpt[x]=dpt[fa[x]]+1;
    for(i=1;i<=15;i++)
        ancestor[x][i]=ancestor[ancestor[x][i-1]][i-1];
    for(i=head[x];i;i=table[i].next)
        if(table[i].to!=fa[x])
        {
            fa[table[i].to]=ancestor[table[i].to][0]=x;
            DFS(table[i].to);
            if(top-bottom>=b1)
            {
                ++_cnt;
                while(top>bottom)
                    belong[stack[top--]]=_cnt;
            }
        }
    stack[++top]=x;
    if(x==1)
    {
        ++_cnt;
        while(top)
            belong[stack[top--]]=_cnt;
    }
}

void Update(int x)
{
    v[x]=true;
    if(a[x]>n) return ;
    cnt[a[x]]++;
    if(cnt[a[x]]==1)
        block[a[x]/b2]++;
}

void Downdate(int x)
{
    v[x]=false;
    if(a[x]>n) return;
    cnt[a[x]]--;
    if(!cnt[a[x]])
        block[a[x]/b2]--;
}

int LCA(int x,int y)
{
    int j;
    if(dpt[x]<dpt[y])
        swap(x,y);
    for(j=15;~j;j--)
        if(dpt[ancestor[x][j]]>=dpt[y])
            x=ancestor[x][j];
    if(x==y) return x;
    for(j=15;~j;j--)
        if(ancestor[x][j]!=ancestor[y][j])
            x=ancestor[x][j],y=ancestor[y][j];
    return ancestor[x][0];
}

void Transfer(int x,int y)
{
    int lca=LCA(x,y);
    for(;x!=lca;x=fa[x])
    {
        if(v[x]) Downdate(x);
        else Update(x);
    }
    for(;y!=lca;y=fa[y])
    {
        if(v[y]) Downdate(y);
        else Update(y);
    }
}

int Get_Mex()
{
    int i,j;
    for(i=0;;i++)
        if(block[i]!=b2)
            for(j=i*b2;;j++)
                if(!cnt[j])
                    return j;
}

int main()
{
    int i,p,x,y;
    cin>>n>>m;
    b1=pow(n,2.0/3.0)+1e-7;
    b2=sqrt(n)+1e-7;
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        Add(x,y);Add(y,x);
    }
    DFS(1);
    for(i=1;i<=m;i++)
    {
        scanf("%d%d%d",&p,&x,&y);
        if(p==0)
        {
            modifictions[++c].x=x;
            modifictions[  c].from=a[x];
            modifictions[  c].to=y;
            modifictions[  c].t=i;
            a[x]=y;
        }
        else
        {
            if(belong[x]>belong[y])
                swap(x,y);
            queries[++q].x=x;
            queries[  q].y=y;
            queries[  q].t=i;
        }
    }
    t=c;
    sort(queries+1,queries+q+1);
    for(i=1;i<=q;i++)
    {
        int lca=LCA(queries[i].x,queries[i].y);
        Transfer(L,queries[i].x);
        Transfer(R,queries[i].y);
        L=queries[i].x;
        R=queries[i].y;
        while( modifictions[t].t > queries[i].t )
        {
            if(v[modifictions[t].x])
            {
                Downdate(modifictions[t].x);
                a[modifictions[t].x]=modifictions[t].from;
                Update(modifictions[t].x);
            }
            else
                a[modifictions[t].x]=modifictions[t].from;
            --t;
        }
        while( t<c && modifictions[t+1].t < queries[i].t )
        {
            if(v[modifictions[t+1].x])
            {
                Downdate(modifictions[t+1].x);
                a[modifictions[t+1].x]=modifictions[t+1].to;
                Update(modifictions[t+1].x);
            }
            else
                a[modifictions[t+1].x]=modifictions[t+1].to;
            ++t;
        }
        Update(lca);
        queries[i].ans=Get_Mex();
        Downdate(lca);
    }
    sort(queries+1,queries+q+1,Compare);
    for(i=1;i<=q;i++)
        printf("%d\n",queries[i].ans);
    return 0;
}
时间: 2024-10-29 19:10:18

BZOJ 4129 Haruna’s Breakfast 带修改树上莫队+分块的相关文章

BZOJ 3052 WC2013 糖果公园 带修改树上莫队

题目大意:给定一棵树,每个点有一个颜色,提供两种操作: 1.询问两点间路径上的Σv[a[i]]*w[k],其中a[i]代表这个点的颜色,k表示这个点是这种颜色第k次出现 2.修改某个点的颜色 VfleaKing的题解见 http://vfleaking.blog.163.com/blog/static/174807634201311011201627/ 带修改莫队上树--如果不带修改就正常搞就好了 如果带修改的话,令块的大小为n^(2/3) 将询问排序时第一键值为左端点所在块,第二键值为右端点所

bzoj 2120: 数颜色(带修改的莫队算法)

2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MB Submit: 2908  Solved: 1130 [Submit][Status][Discuss] Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P Col 把第P支画笔替换为颜色Col.为了满足墨墨的要求,你知道你需

BZOJ 2120: 数颜色 带修改的莫队算法 树状数组套主席树

https://www.lydsy.com/JudgeOnline/problem.php?id=2120 标题里是两种不同的解法. 带修改的莫队和普通莫队比多了个修改操作,影响不大,但是注意一下细节不要出现zz错误. 这道题修改的数量比较少可以写莫队,但是如果修改数量多或者是特别极限的数据大概是不行的吧. 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstrin

带修改的莫队算法学习小记

简介 莫涛大神创造出的离线询问算法的带修改版. 算法基础:需要掌握莫队算法,会打暴搜(暴力). 一个叫莫的双端队列. 只支持单点修改 操作方法 普通的不带修改的莫队算法要把每个询问带上两个关键字排序,现在待修改的莫队算法要带上三个关键字排序. 初始操作 fo(i,1,m) { scanf("%s%d%d",s,&k,&l); if (s[0]=='Q')a[++tot].l=k,a[tot].r=l,a[tot].x=num,a[tot].p=tot; else d[+

带修改的莫队

在学习了最基础的莫队后,我们会发现普通莫队并不资瓷修改操作啊!!!这就很尴尬,那么莫队就没办法修改吗,反正当时发明莫队的人是没有提到的,但是不要小瞧了智慧的OI人,不久就有人就提出了带修改莫队的想法. 如果你还没不知道莫队 点击这里!!! 其实刚知道莫队还可以资瓷修改时,我以为代码量会有质的飞越,但是学习后才发现原来不过如此,所以就别担心了... 首先还是来一道题 数颜色 题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1.

[BZOJ 4129]Haruna’s Breakfast(树上带修改莫队)

Description Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了一棵 树上,每个结点都有一样食材,Shimakaze要考验一下她. 每个食材都有一个美味度,Shimakaze会进行两种操作: 1.修改某个结点的食材的美味度. 2.对于某条链,询问这条链的美味度集合中,最小的未出现的自然数是多少.即mex值. 请你帮帮Haruna吧. Solution 树上带修改莫队 统计答案的时候也分块查询,找到第一个没满的块开始一个一个找 #include<i

bzoj 3809 Gty的二逼妹子序列 —— 莫队+分块

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3809 据说一开始应该想到莫队+树状数组,然而我想的却是莫队+权值线段树... 如果用权值线段树,则修改和查询都是 O(logn),总复杂度 O(n√nlogn),艰难...(而且仔细一看空间有点卡?) 看了TJ,才发现权值也可以分块,则查询 O(√n) 但修改 O(1),就可以过咯~ 代码如下: #include<iostream> #include<cstdio> #inc

BZOJ 2120 数颜色&amp;2453 维护队列 [带修改的莫队算法]【学习笔记】

题意: 询问区间中不同颜色的个数,单点修改颜色 发现以前写的学习笔记没法看,于是重写一下(不就是会用latex了嘛) 额外维护一个当前修改操作执行到的时间 如果要进行某个查询操作,修改操作的时间必须移动到这个查询操作处 按照$(pos[l], pos[r], tim)$排序 令$S=N^{\frac{2}{3}}$, 有$N^{\frac{1}{3}}$块 $l$移动$N*N^{\frac{2}{3}}$次 $r$移动$N*N^{\frac{1}{3}}+N*N^{\frac{2}{3}}$次

Bzoj 3809: Gty的二逼妹子序列 莫队,分块

3809: Gty的二逼妹子序列 Time Limit: 35 Sec  Memory Limit: 28 MBSubmit: 868  Solved: 234[Submit][Status][Discuss] Description Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题. 对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数. 为了方便,我们规定妹子们的美丽度全都在[1,n]中. 给定一个长度为n(1<=n<=100000)的