【洛谷比赛】你的名字T1 线索

题面

祭典即将举行,编织结绳的工作正在紧张地开展着。而这天,泷和三叶交换了身体,三叶担心泷不会编结绳,在日记里留下了编织结绳的方法,并请你来帮助泷编好结绳。

将丝线汇集在一起,编织成形;扭曲,缠绕,有时又还原,再连接;那就是结,那就是时间。

结绳是神的思想的重要载体。编织结绳有两个基本操作:染色和交换。染色是为了寄托人民对美好生活的向往,而交换则是要在线与线之间、人与人之间建立联系,形成结,建立羁绊。

现在泷要编织由n条丝线组成的结绳。这nn条结绳紧紧排成一排,按位置把它们叫作第1,2,,n条丝线。编织开始前,每条丝线有自己的颜色(用一个正整数来表示),第i(1in)条丝线颜色为ci

三叶给泷的编织方法有m步,第j(1jm)步用44个正整数aj,lj,rj,xj来描述。aj的值为1或2。

aj=1,则表示这步操作为染色,这时要把[lj,rj]这个区间上的丝线全部染成xj这种颜色,保证ljrj

aj=2,则表示这步操作为交换,这时要把lj位置上的丝线和rj位置上的丝线交换。作为它们交换的纪念,交换的同时要把这两条丝线染成xj这种颜色。注意,aj=2时不保证ljrj,但保证ljrj

两条丝线交换后会形成永久的联系。这种联系体现在,交换发生后,若其中任意一条丝线被染上了某种颜色,另一条丝线也会被同时染上相同的颜色。这种羁绊还具有传递性,即如果1与2建立了羁绊,2又3建立了羁绊,那么我们就认为1也与3建立了羁绊。注意,丝线不能与自己形成结。

注意,如果交换的两根丝线在交换前已经建立了联系,进行交换操作后它们的联系不会改变,但仍要对它们染色以示纪念。

为了检查编织的效果,泷想知道编织完毕后,每一个位置上丝线的颜色。此外,为了保证结绳的联系足够牢固,泷还需要知道与每条丝线建立联系的丝线的数目。你能帮助他吗?

输入格式:

输入共(m+2)行。
1行有2个以空格分隔的正整数n,m,分别代表丝线的数目和编织步骤的数目。
2行有n个以空格分隔的正整数,第i个正整数ci表示编织开始前第i条丝线的颜色。
以下m行每行有4个以空格分隔的正整数aj,lj,rj,xj,描述编织的步骤,意义如上所述。

输出格式:

输出共2行。
1行有n个以空格分隔的正整数,第ii个正整数ci代表编织完毕后第ii个位置上的丝线的颜色。
2行有n个以空格分隔的非负整数,第ii个非负整数di代表编织完毕后与第ii个位置上的丝线建立联系的丝线数目。

分析

作为T1,就考了一个不裸的线段树,我觉得还是有点恐怖了。然而我似乎是忽略了题目顺序是按剧情来的...

但是也能一眼看出来是线段树+并查集,但是具体怎么实现呢?

我们把时间作为lazy标记,时间大的颜色会覆盖时间小的颜色,所以我们不需要完全更新每个区间。

对于一个区间[l,r],直接区间修改[l,r]

对于一个交换操作,只更新l的颜色,并把l和r并入一个集合之中。

再最后搜索答案的时候,只需要把同一个集合中,时间最晚的那一次修改作为集合的颜色即可

代码

#include<bits/stdc++.h>
using namespace std;
#define N 100100
#define ll long long
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (t[p].l+t[p].r>>1)
int n,m;
int fa[N],col[N],bel[N],siz[N],colt[N];
struct email
{
    int l,r,c,ti;
}t[N*4];

inline int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}

void pushnow(int p,int v)
{
    if(t[p].ti>=t[v].ti)
        t[v].ti=t[p].ti,t[v].c=t[p].c;
}

void pushdown(int p)
{
    if(t[p].ti)
    {
        pushnow(p,lc);pushnow(p,rc);
        t[p].ti=0;
    }
}

void update(int p,int ql,int qr,int color,int nowt)
{
    if(ql<=t[p].l&&qr>=t[p].r)
    {
        t[p].ti=nowt;t[p].c=color;
        return ;
    }
    pushdown(p);
    if(ql<=mid)update(lc,ql,qr,color,nowt);
    if(qr>mid)update(rc,ql,qr,color,nowt);
}

void build(int p,int l,int r)
{
    t[p].l=l,t[p].r=r;
    if(l==r)
    {
        t[p].c=col[l];
        return;
    }
    int bm=l+r>>1;
    build(lc,l,mid);build(rc,mid+1,r);
}

void query(int p)
{
    if(t[p].l==t[p].r)
    {
        bel[t[p].l]=find(t[p].l);
        siz[bel[t[p].l]]++;
        if(colt[bel[t[p].l]]<t[p].ti)
        {
            colt[bel[t[p].l]]=t[p].ti;
            col[bel[t[p].l]]=t[p].c;
        }
        return ;
    }
    pushdown(p);
    query(lc);query(rc);
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&col[i]);
    for(int i=1;i<=n;i++)fa[i]=i;
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int op,li,ri,xi;
        scanf("%d%d%d%d",&op,&li,&ri,&xi);
        if(op==1)
            update(1,li,ri,xi,i);
        else
        {
            int fl=find(li),fr=find(ri);
            if(fl!=fr)
                fa[fl]=fr;
            update(1,li,li,xi,i);
        }    
    }
    query(1);
    for(int i=1;i<=n;i++)
        printf("%d ",col[bel[i]]);
    printf("
");
    for(int i=1;i<=n;i++)
        printf("%d ",siz[bel[i]]-1);
    return 0;
}
“Make my parents proud,and impress the girl I like.”
原文地址:https://www.cnblogs.com/NSD-email0820/p/9743513.html