• Jzoj5419 筹备计划


    题目背景
           热烈庆祝北京师范大学附属实验中学成立100周年!
    问题描述
           校庆筹备组的老师们正在寻找合适的地方来举办校庆庆典。
           学生们的位置和可以举办庆典的位置在x轴的正半轴取值在[1,n]的整数位置上。
           老师们选择的地点是会根据参加典礼的学生位置来决定的,具体来说:定义一个位置的距离和为该位置到所有参加学生的距离之和。如果一个位置的距离和最小,且它比所有和它距离和相等的位置的位置更靠左,则老师们会选择这个位置。
           开始时,所有的位置都可以举办庆典。但很可惜的是,并不是所有的位置都能举办庆典,有些奇怪的事件会使[l,r]这段区间不能举办庆典,不过有时也会使[l,r]可以重新举办庆典(并不保证[l,r]之前的每个位置都不能举办庆典)。
           有时一些学生会因为某些原因不能参加庆典,有时一些学生会主动报名参加庆典。
           作为一名合格的老师,你需要求出每个事件发生后庆典应该选择的位置,如果没有合法位置,请输出-1。

    数据结构什么的最无脑了2333

    贪心,首先先来说没有奇怪事件的情况

    很明显就是一个带权中位数了,可以用一个树状数组+二分搞定

    那么加上了奇怪事件,那么显然,如果最优位置被覆盖后,显然选择的位置离最有位置越近越优,所以用一个线段树区间覆盖,让后二分找出离最优点最近的两个取较优即可

    代码长度碾压所有其他选手,然而时间几乎垫底

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define LL long long
    #define N 200010
    #define mid (l+r>>1)
    using namespace std;
    int n,m; bool vis[N]; LL S=0;
    struct Seg{
    	LL s[N],c[N],v;
    	LL cum(int x){ for(v=0;x;x^=x&-x) v+=c[x]; return v; }
    	LL sum(int x){ for(v=0;x;x^=x&-x) v+=s[x]; return v; }
    	void add(int x,LL k){ for(v=k*x;x<=n;x+=x&-x) s[x]+=v,c[x]+=k; }
    	LL gC(int l,int r){ return cum(r)-cum(l-1); }
    	LL gS(int l,int r){ return sum(r)-sum(l-1); }
    } s;
    int w[N<<2],t[N<<2];
    inline void pd(int x,int m){ 
    	if(t[x]){
    		t[x<<1]=t[x];
    		t[x<<1|1]=t[x]; --t[x];
    		w[x<<1]=t[x];
    		w[x<<1|1]=t[x];
    		t[x]=0;
    	}
    }
    void build(int l,int r,int x){
    	if(l==r){ w[x]=1; t[x]=0; return; }
    	build(l,mid,x<<1); build(mid+1,r,x<<1|1);
    	w[x]=w[x<<1]|w[x<<1|1];
    }
    void update(int l,int r,int x,int L,int R,int k){
    	if(L<=l && r<=R){ w[x]=k; t[x]=k+1; return; }
    	pd(x,r-l+1);
    	if(L<=mid) update(l,mid,x<<1,L,R,k);
    	if(mid<R) update(mid+1,r,x<<1|1,L,R,k);
    	w[x]=w[x<<1]|w[x<<1|1];
    }
    int query(int l,int r,int x,int L,int R){
    	if(L<=l && r<=R) return w[x];
    	pd(x,r-l+1); int ans=0;
    	if(L<=mid) ans|=query(l,mid,x<<1,L,R);
    	if(mid<R) ans|=query(mid+1,r,x<<1|1,L,R);
    	return ans;
    }
    LL cal(int j){
    	if(j<1 || j>n) return 1ll<<60;
    	LL c,A; 
    	c=s.gC(1,j-1); A=c*j-s.gS(1,j-1);
    	c=s.gC(j+1,n); A+=s.gS(j+1,n)-j*c;
    	return A;
    }
    int prt2(){
    	freopen("position.in","r",stdin);
    	freopen("position.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(int x,i=1;i<=n;++i){
    		scanf("%d",&x);
    		s.add(i,x); S+=x;
    	} build(1,n,1);
    	for(int o,l,r,p,M;m--;){
    		scanf("%d%d%d",&o,&l,&r);
    		if(o==1){ s.add(l,r); S+=r; }
    		else if(o==2){ s.add(l,-r); S-=r; }
    		else if(o==3) update(1,n,1,l,r,1);
    		else update(1,n,1,l,r,0);
    		l=1,r=n;
    		for(;l<r;){
    			M=l+r>>1;
    			if((s.gC(1,M)<<1)<S) l=M+1;
    			else r=M;
    		}
    		p=l;
    		if(query(1,n,1,p,p)) printf("%d
    ",p);
    		else {
    			for(l=0,r=p-1;l<r;){
    				M=l+r+1>>1;
    				if(query(1,n,1,M,p)) l=M;
    				else r=M-1;
    			}
    			o=l;
    			for(l=p+1,r=n+1;l<r;){
    				M=l+r>>1;
    				if(query(1,n,1,p,M)) r=M;
    				else l=M+1;
    			}
    			if(o==0 && l==n+1) puts("-1");
    			else printf("%d
    ",cal(o)>cal(l)?l:o);
    		}
    	}
    }
    int main(){ prt2(); }

  • 相关阅读:
    微服务迁移记(二):注册中心(consul搭建)
    微服务迁移记(一):技术架构
    小程序入坑记录
    不思量,自难忘:我的10年程序生涯
    your password has expired.to log in you must change it
    Javascript中 a.href 和 a.getAttribute('href') 结果不完全一致
    PHP不使用递归的无限级分类
    百度移动搜索自动转码太坑爹,JS跳转地址会被抓取
    iScroll 下 a 标签失效
    浏览器的云加速可能导致IP统计异常
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477229.html
Copyright © 2020-2023  润新知