zoukankan      html  css  js  c++  java
  • 【题解】Luogu P5251 [LnOI2019]第二代图灵机

    原题传送门

    前置芝士:珂朵莉树

    珂朵莉树的主要功能是区间赋值

    这道题还算明显(操作2)

    一开始看见这题觉得很毒瘤,但仔细想想发现颜色和数字之间没有什么关系

    我们一共要维护三个东西:

    1.区间和:树状数组就珂以了

    2.区间最大值:写棵线段树

    3.颜色:写珂朵莉树

    查询的是连续的区间,尺取法就珂以了(尺取法就像单调队列一样)

    复杂度:(O(qlog^2n))(q次查询,尺取平均(log n),线段树/树状数组(log n))

    #include <bits/stdc++.h>
    #define IT set<node>::iterator 
    #define N 100005
    #define inf 0x3f3f3f3f
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register int x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    inline int Max(register int a,register int b)
    {
    	return a>b?a:b;
    }
    inline int Min(register int a,register int b)
    {
    	return a<b?a:b;
    }
    int n,m,cs;
    int t[N];
    inline void update(register int x,register int val)
    {
    	for(register int i=x;i<=n;i+=i&(-i))
    		t[i]+=val;
    }
    inline int query(register int x)
    {
    	int res=0;
    	for(register int i=x;i;i-=i&(-i))
    		res+=t[i];
    	return res;
    }
    inline int ask(register int l,register int r)
    {
    	return query(r)-query(l-1);
    }
    int tr[N<<3];
    inline void pushup(register int x)
    {
    	tr[x]=Max(tr[x<<1],tr[x<<1|1]);
    }
    inline void updatemaxx(register int x,register int l,register int r,register int pos,register int val)
    {
    	if(l==r)
    	{
    		tr[x]=val;
    		return;
    	}
    	int mid=l+r>>1;
    	if(pos<=mid)
    		updatemaxx(x<<1,l,mid,pos,val);
    	else
    		updatemaxx(x<<1|1,mid+1,r,pos,val);
    	pushup(x);
    }
    inline int querymaxx(register int x,register int l,register int r,register int L,register int R)
    {
    	if(L<=l&&r<=R)
    		return tr[x];
    	int res=0,mid=l+r>>1;
    	if(L<=mid)
    		res=Max(res,querymaxx(x<<1,l,mid,L,R));
    	if(R>mid)
    		res=Max(res,querymaxx(x<<1|1,mid+1,r,L,R));
    	return res;
    }
    struct node{
    	int l,r;
    	mutable int v;
    	node(int L,int R=-1,int V=0):l(L),r(R),v(V){}
    	bool operator<(const node& o)const{
    		return l<o.l;
    	}
    };
    set<node> s;
    IT split(register int pos)
    {
    	IT it=s.lower_bound(node(pos));
    	if(it!=s.end()&&it->l==pos)
    		return it;
    	--it;
    	int L=it->l,R=it->r,V=it->v;
    	s.erase(it);
    	s.insert(node(L,pos-1,V));
    	return s.insert(node(pos,R,V)).first;
    }
    inline void assign_val(register int l,register int r,register int val)
    {
    	IT itr=split(r+1),itl=split(l);
    	s.erase(itl,itr);
    	s.insert(node(l,r,val));
    }
    int tex[N];
    inline int query1(register int l,register int r)
    {
    	int ans=inf,left=cs;
    	memset(tex,0,sizeof(tex));
    	IT itr=split(r+1),itl=split(l),L,R;
    	--itl;
    	L=R=itl;
    	while(R!=itr)
    	{
    		if(L!=itl)
    		{
    			if(--tex[L->v]==0)
    				++left;
    		}
    		++L;
    		while(left&&R!=itr)
    		{
    			++R;
    			if(++tex[R->v]==1)
    				--left;
    		}
    		if(R==itr)
    			break;
    		while(!left&&L!=R)
    		{
    			if(--tex[L->v]==0)
    				++left;
    			++L;
    		}
    		if(left)
    		{
    			--L;
    			++tex[L->v];
    			--left;
    		}
    		ans=Min(ans,ask(L->r,R->l));
    	}
    	return ans;
    }
    int p[N];
    inline int query2(register int l,register int r)
    {
    	memset(p,0,sizeof(p));
    	int ans=querymaxx(1,1,n,l,r);
    	IT itr=split(r+1),itl=split(l),L,R;
    	R=itl--;
    	L=itl;
    	while(R!=itr)
    	{
    		if(L!=itl)
    			p[L->v]=0;
    		++L;
    		p[L->v]=1;
    		while(R->l<L->r)
    			++R;
    		if(L==R)
    			++R;
    		if(R==itr)
    			break;
    		while(!p[R->v]&&R!=itr&&R->l==R->r)
    		{
    			p[R->v]=1;
    			++R;
    		}
    		if(R==itr)
    			--R;
    		else if(!p[R->v])
    			p[R->v]=1;
    		else
    			--R;
    		if(L==R)
    			continue;
    		ans=Max(ans,ask(L->r,R->l));
    	}
    	return ans;
    }
    int main()
    {
    	n=read(),m=read(),cs=read();
    	s.insert(node(0,0,-1)),s.insert(node(n+1,n+1,-1));
    	for(register int i=1;i<=n;++i)
    	{
    		int x=read();
    		update(i,x);
    		updatemaxx(1,1,n,i,x);
    	}
    	for(register int i=1;i<=n;++i)
    	{
    		int x=read();
    		s.insert(node(i,i,x));
    	}
    	int opt,l,r,x;
    	while(m--)
    	{
    		opt=read();
    		if(opt==1)
    		{
    			l=read(),x=read();
    			update(l,x-ask(l,l));
    			updatemaxx(1,1,n,l,x);
    		}
    		else if(opt==2)
    		{
    			l=read(),r=read(),x=read();
    			assign_val(l,r,x);
    		}
    		else if(opt==3)
    		{
    			l=read(),r=read();
    			int ans=query1(l,r);
    			if(ans==inf)
    				puts("-1");
    			else
    				write(ans),puts("");
    		}
    		else
    		{
    			l=read(),r=read();
    			write(query2(l,r)),puts("");
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    阿里妈妈又做了新工具,帮你把 Vue2 代码改成 Vue3 的
    gulp安装出错
    js操作select
    linux基本命令说明参数
    Linux基础——vim编辑器的使用
    常见报错——Uncaught TypeError: document.getElementsByClassName(...).addEventListener is not a function
    IE浏览器hack方法总结之条件注释判断
    浏览器兼容
    安好
    jQuery调整表列(左右拉动调整列宽)插件__colResizable,动态列如何使用
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10507386.html
Copyright © 2011-2022 走看看