• 2022729 #21 P6717


    今天花了点时间看完了 淤泥之花与空心石,只能说是神作了!(时长共计 12h,看的非常过瘾)

    055 P6717 [CCO2018] Boring Lectures

    我们将序列按照 \(k\) 分块,断言答案中至少会有一个块内最大值。

    反证法,令最优决策为 \(a,b\),若在同一块,明显把较小的改为块内最大值更优;否则在相邻块,令最大值分别为 \(c,d\),有:

    \[a+b>a+c,a+b>b+d\\\Rightarrow b>c,a>d \]

    显然矛盾。

    于是维护每一块最大值对应的匹配,放在堆里维护即可,复杂度 \(O((n+q)\log n)\)

    #include<stdio.h>
    #include<queue>
    #define lc(x) (x<<1)
    #define rc(x) (x<<1|1)
    #define mid (l+r>>1)
    using namespace std;
    const int maxn=1000005,maxt=maxn<<2;
    int n,k,T,bt,stp;
    int mx[maxt],a[maxn],bel[maxn],bl[maxn],br[maxn],vis[maxn];
    priority_queue< pair<int, pair<int,int> > >q;
    inline void pushup(int now){
    	mx[now]=a[mx[lc(now)]]>a[mx[rc(now)]]? mx[lc(now)]:mx[rc(now)];
    }
    void build(int l,int r,int now){
    	if(l==r){
    		mx[now]=l;
    		return ;
    	}
    	build(l,mid,lc(now)),build(mid+1,r,rc(now)),pushup(now);
    }
    void modify(int l,int r,int now,int p){
    	if(l==r)
    		return ;
    	if(p<=mid)
    		modify(l,mid,lc(now),p);
    	else modify(mid+1,r,rc(now),p);
    	pushup(now);
    }
    int query(int l,int r,int now,int L,int R){
    	if(L<=l&&r<=R)
    		return mx[now];
    	if(L<=mid&&mid<R){
    		int ls=query(l,mid,lc(now),L,R),rs=query(mid+1,r,rc(now),L,R);
    		return a[ls]>a[rs]? ls:rs;
    	}
    	if(L<=mid)
    		return query(l,mid,lc(now),L,R);
    	return query(mid+1,r,rc(now),L,R);
    }
    void answer(){
    	while(!q.empty()&&vis[q.top().second.first]!=q.top().second.second)
    		q.pop();
    	printf("%d\n",q.top().first);
    }
    void insert(int id){
    	int p=query(1,n,1,bl[id],br[id]),c=-1;
    	swap(c,a[p]),modify(1,n,1,p);
    	vis[id]=stp,q.push(make_pair(c+a[query(1,n,1,max(1,p-k+1),min(n,p+k-1))],make_pair(id,stp)));
    	swap(c,a[p]),modify(1,n,1,p);
    }
    int main(){
    	scanf("%d%d%d",&n,&k,&T),bt=n/k;
    	for(int i=1;i<=n;i++)
    		scanf("%d",&a[i]);
    	for(int i=1;i<=bt;i++)
    		bl[i]=br[i-1]+1,br[i]=i*k;
    	if(br[bt]<n)
    		bt++,bl[bt]=br[bt-1]+1,br[bt]=n;
    	build(1,n,1);
    	stp=1;
    	for(int i=1;i<=bt;i++){
    		for(int j=bl[i];j<=br[i];j++)
    			bel[j]=i;
    		insert(i);
    	}
    	answer();
    	for(int i=1,x,y;i<=T;i++){
    		scanf("%d%d",&x,&y),a[x]=y,modify(1,n,1,x);
    		stp++;
    		if(bel[x]>1)
    			insert(bel[x]-1);
    		insert(bel[x]);
    		if(bel[x]<bt)
    			insert(bel[x]+1);
    		answer();
    	}
    	return 0;
    }
    
  • 相关阅读:
    注意力机制的命名实体识别
    tfidf_CountVectorizer 与 TfidfTransformer 保存和测试
    转载:UML学习(三)-----序列图(silent)
    转载:UML学习(二)-----类图(silent)
    转载:UML学习(一)-----用例图 (silent)
    转载:Practical UML™: A Hands-On Introduction for Developers
    转载:gc的概念,如果A和B对象循环引用,是否可以被GC?
    转载:Java高并发,如何解决,什么方式解决
    转载:消息队列应用场景
    转载:详解Java 自动装箱与拆箱的实现原理
  • 原文地址:https://www.cnblogs.com/xiaoziyao/p/16530965.html
Copyright © 2020-2023  润新知