• 【题解】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;
    }
    
    
  • 相关阅读:
    对象属性编辑器中实现像Size,Rectangle等可以展开的属性
    远程办公产品风口会不会把SOHO自由职业吹起来
    项目加
    推荐几款免费又好用的项目管理工具
    Sprint Retrospective
    敏捷管理的大概背景和Scrum的特性
    推荐几款最好用的项目管理系统,即好用又免费
    项目管理的需求变更问题
    敏捷管理有一个原则就是:拥抱变化
    推荐5款体验最好的项目管理工具
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10507386.html
Copyright © 2020-2023  润新知