zoukankan      html  css  js  c++  java
  • 梦幻布丁——奇妙的线段树合并

    description

    (n) 个布丁摆成一行,进行 (m) 次操作。每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色。

    solution

    线段树合并板子,用到动态开点.复杂度看似高,由于答案单调不增,所以实际上均摊下来只有(Omicron(nlog n))的复杂度.代码贴这里方便复习吧.

    code

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<ctime>
    #define R register
    #define next MabLcdG
    #define mod 1
    #define debug puts("mlg")
    #define Mod(x) ((x%mod+mod)%mod)
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    inline ll read();
    inline void write(ll x);
    inline void writesp(ll x);
    inline void writeln(ll x);
    ll n,m;
    const ll maxn=1e6;
    struct Seg{
    	ll lc,rc,lv,rv,dat;
    }t[maxn<<2];
    ll rt[maxn];
    ll cnt;
    inline void update(ll p){
    	t[p].lv=t[p].lc?t[t[p].lc].lv:t[t[p].rc].lv;
    	t[p].rv=t[p].rc?t[t[p].rc].rv:t[t[p].lc].lv;
    	t[p].dat=t[t[p].lc].dat+t[t[p].rc].dat-(t[t[p].lc].rv+1==t[t[p].rc].lv);
    }
    
    inline void change(ll &p,ll l,ll r,ll x){
    	if(!p) p=++cnt;
    	if(l==r){t[p].lv=t[p].rv=x;t[p].dat=1;return;}
    	ll mid=l+r>>1;
    	if(x<=mid) change(t[p].lc,l,mid,x);
    	else change(t[p].rc,mid+1,r,x);
    	update(p);
    }
    
    inline void merge(ll &x,ll &y,ll l,ll r){
    	if(!x||!y){x+=y;return;}
    	if(l==r){t[x].lv=t[x].rv=l;t[x].dat=1;return;}
    	ll mid=l+r>>1;
    	merge(t[x].lc,t[y].lc,l,mid);
    	merge(t[x].rc,t[y].rc,mid+1,r);
    	update(x);
    }
    ll ans;
    int main(){
    	n=read();m=read();
    	for(R ll i=1,x;i<=n;i++){
    		x=read();
    		ans-=t[rt[x]].dat;
    		change(rt[x],1,n,i);
    		ans+=t[rt[x]].dat;
    	}
    	while(m--){
    		ll op=read();
    		if(op==1){
    			ll x=read(),y=read();
    			if(x==y) continue;
    			ans-=t[rt[x]].dat;
    			ans-=t[rt[y]].dat;
    			merge(rt[y],rt[x],1,n);
    			rt[x]=0;
    			ans+=t[rt[y]].dat;
    		}
    		else{
    			writeln(ans);
    		}
    	}
    } 
    inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;}
    inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');}
    inline void writesp(ll x){write(x);putchar(' ');}
    inline void writeln(ll x){write(x);putchar('
    ');}
    
  • 相关阅读:
    鼠标移入和鼠标移出的提示,和样式的转换
    HTML5——新特性,拖放
    关于订阅发布模式
    titanium环境配置
    Matlab与C混编的介绍
    一个相对健壮的node 静态http服务器
    阻赛非阻塞同步异步
    最近在做的事以及一些安排
    说一说js中__proto__和prototype以及原型继承的那些事
    PHP写的爬虫,爬指定网站页面上的各种图片
  • 原文地址:https://www.cnblogs.com/ylwtsq/p/13450195.html
Copyright © 2011-2022 走看看