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('
    ');}
    
  • 相关阅读:
    SQL Server Audit监控触发器状态
    SQL Server 数据变更时间戳(timestamp)在复制中的运用
    SQL Server 更改跟踪(Chang Tracking)监控表数据
    SQL Server 变更数据捕获(CDC)监控表数据
    SQL Server 事件通知(Event notifications)
    SQL Server 堆表行存储大小(Record Size)
    SQL Server DDL触发器运用
    SQL Server 默认跟踪(Default Trace)
    SQL Server 创建数据库邮件
    SQL Server 跨网段(跨机房)FTP复制
  • 原文地址:https://www.cnblogs.com/ylwtsq/p/13450195.html
Copyright © 2011-2022 走看看