Codeforces911 G. Mass Change Queries(分块,时间换空间技巧)

Posted live4m

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces911 G. Mass Change Queries(分块,时间换空间技巧)相关的知识,希望对你有一定的参考价值。

题意:

解法:

拆分sq个块,
每个块开大小为100的数组rt[][],维护100种颜色的并查集节点,
每个并查集节点维护节点的颜色.
rt[i][x]表示第i个块,颜色为x的并查集节点编号.

对于每个修改,如果x==y则不直接返回,
否则根据分块性质,只需要处理中间的sq个块和边缘的两个块.

对于中间的块:
将rt[i][x]的父节点修改为rt[i][y],然后新建一个新的rt[i][x].

对于边缘的块:
遍历下标i,如果颜色为x,那么根节点设置为rt[bel[i]][y],bel[i]表示点i所在的块.

总复杂度O(q*sq).
这题block取sqrt(n)的话,会MLE,
一个技巧是放大块的大小,取block=sqrt(n)*3就能过了.

code:

#include <bits/stdc++.h>

using namespace std;
const int maxm=2e5+5;
const int sq=300;
int pre[maxm*sq],idx;
int val[maxm*sq];
int L[sq],R[sq];
int rt[sq][101];
int bel[maxm];
int a[maxm];
int block,num;
int n,q;
int ffind(int x)
    return pre[x]==x?x:pre[x]=ffind(pre[x]);

inline int newNode(int c)
    idx++;pre[idx]=idx;val[idx]=c;return idx;

void init()
    idx=n;
    block=sqrt(n)*3;
    block=min(block,n);
    num=n/block;
    assert(num<=sq);//
    if(n%block)num++;
    for(int i=1;i<=num;i++)
        L[i]=(i-1)*block+1;
        R[i]=i*block;
    
    R[num]=n;
    for(int i=1;i<=num;i++)
        for(int j=1;j<=100;j++)
            rt[i][j]=newNode(j);
        
        for(int j=L[i];j<=R[i];j++)
            bel[j]=i;
            pre[j]=rt[i][a[j]];
        
    

void cal()
    int l,r,x,y;scanf("%d%d%d%d",&l,&r,&x,&y);
    if(x==y)return ;
    if (bel[l]==bel[r])
        int &ny=rt[bel[l]][y];
        for(int i=l;i<=r;i++)
            int c=val[ffind(i)];
            if (c==x)
                pre[i]=ny;
            
        
    
    else
        //中间块
        for (int i=bel[l]+1;i<bel[r];i++)
            pre[rt[i][x]]=rt[i][y];
            rt[i][x]=newNode(x);
        
        //左边缘块
        int &nyL=rt[bel[l]][y];
        for (int i=l;i<=R[bel[l]];i++)
            int c=val[ffind(i)];
            if (c==x)
                pre[i]=nyL;
            
        
        //右边缘块
        int &nyR=rt[bel[r]][y];
        for (int i=L[bel[r]];i<=r;i++)
            int c=val[ffind(i)];
            if(c==x)
                pre[i]=nyR;
            
        
    

void solve()
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    
    init();
    scanf("%d",&q);
    while(q--)
        cal();
    
    for(int i=1;i<=n;i++)
        int c=val[ffind(i)];
        printf("%d ",c);
    
    puts("");

int main()
    // ios::sync_with_stdio(0);
    #ifndef ONLINE_JUDGE
    freopen("../in.txt", "r", stdin);
    freopen("../out.txt", "w", stdout);
    #endif
    solve();
    return 0;


以上是关于Codeforces911 G. Mass Change Queries(分块,时间换空间技巧)的主要内容,如果未能解决你的问题,请参考以下文章

Mass Change Queries Codeforces - 911G

Mass Change Queries CodeForces - 911G (线段树合并)

[CF911G]Mass Change Queries

CF911G Mass Change Queries (线段树区间 合并)

Codeforces G. Ant colony

Codeforces G. Ciel the Commander