zoukankan      html  css  js  c++  java
  • 【YbtOJ#20066】筹备计划

    题目

    题目链接:http://noip.ybtoj.com.cn/contest/90/problem/4

    思路

    这种题就硬缝合。。。
    显然能造成贡献的是学生人数中位数左右的可以被选则的点。
    维护一棵树状数组维护学生人数以及带权学生人数(也就是第 \(i\) 个位置的学生人数 \(\times i\))(下文称前者为树状数组 1,后者为树状数组 2),以及可以线段树维护可以被选中的区间。
    先求出树状数组 1 全局的和,求出其中位数 \(sum\),再用树状数组二分求出中位数所在位置 \(p\)
    然后在线段树上用线段树二分求出 \(p\) 前后第一个可以被选择的位置,具体的先在线段树上求出 \(1\sim p\) 的和 \(cnt\),然后二分出第一个和为 \(cnt\)\(cnt+1\) 的位置 \(pos1\)\(pos2\),这两个位置就可能是答案。
    然后我们求出 \(pos1\)\(pos2\) 的答案并作比较。具体的可以把答案拆开,分成在 \(pos\) 左右两边的答案加起来,而这两边可以用两个树状数组计算出贡献。
    然后取答案较小的那边为答案。
    时间复杂度 \(O(n\log n)\)
    吐槽一下这道题还卡两棵线段树,考场写两棵线段树还没有 XJQ 大爷的 \(O(n\log^2 n)\) 分数高。。。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=200010,M=(1<<18);
    int n,m,a[N];
    
    struct BIT
    {
    	ll c[M+10];
    	
    	void add(int x,ll v)
    	{
    		for (int i=x;i<=M;i+=i&-i)
    			c[i]+=v;
    	}
    	
    	ll query(int x)
    	{
    		ll ans=0;
    		for (int i=x;i;i-=i&-i)
    			ans+=c[i];
    		return ans;
    	}
    	
    	int binary(ll k)
    	{
    		int p=0;
    		for (int i=(M>>1);i>=1;i>>=1)
    			if (k>c[p+i]) k-=c[p+i],p+=i;
    		return p+1;
    	}
    }bit1,bit2;
    
    struct SegTree
    {
    	int l[N*4],r[N*4],sum[N*4],lazy[N*4];
    	SegTree() { memset(lazy,-1,sizeof(lazy)); }
    	
    	void pushup(int x)
    	{
    		sum[x]=sum[x*2]+sum[x*2+1];
    	}	
    
    	void pushdown(int x)
    	{
    		if (lazy[x]!=-1)
    		{
    			lazy[x*2]=lazy[x*2+1]=lazy[x];
    			sum[x*2]=lazy[x]*(r[x*2]-l[x*2]+1);
    			sum[x*2+1]=lazy[x]*(r[x*2+1]-l[x*2+1]+1);
    			lazy[x]=-1;
    		}
    	}
    	
    	void build(int x,int ql,int qr)
    	{
    		l[x]=ql; r[x]=qr;
    		if (ql==qr)
    		{
    			sum[x]=1;
    			return;
    		}
    		int mid=(ql+qr)>>1;
    		build(x*2,ql,mid); build(x*2+1,mid+1,qr);
    		pushup(x);
    	}
    	
    	void update(int x,int ql,int qr,int v)
    	{
    		if (l[x]==ql && r[x]==qr)
    		{
    			sum[x]=v*(r[x]-l[x]+1);
    			lazy[x]=v;
    			return;
    		}
    		pushdown(x);
    		int mid=(l[x]+r[x])>>1;
    		if (qr<=mid) update(x*2,ql,qr,v);
    		else if (ql>mid) update(x*2+1,ql,qr,v);
    		else update(x*2,ql,mid,v),update(x*2+1,mid+1,qr,v);
    		pushup(x);
    	}
    	
    	int query(int x,int ql,int qr)
    	{
    		if (l[x]==ql && r[x]==qr)
    			return sum[x];
    		pushdown(x);
    		int mid=(l[x]+r[x])>>1;
    		if (qr<=mid) return query(x*2,ql,qr);
    		if (ql>mid) return query(x*2+1,ql,qr);
    		return query(x*2,ql,mid)+query(x*2+1,mid+1,qr);
    	}
    	
    	int binary(int x,int k)
    	{
    		if (l[x]==r[x])
    		{
    			if (sum[x]) return l[x];
    				else return -1;
    		}
    		pushdown(x);
    		if (sum[x*2]>=k) return binary(x*2,k);
    			else return binary(x*2+1,k-sum[x*2]);
    	}
    }seg;
    
    int main()
    {
    	freopen("position.in","r",stdin);
    	freopen("position.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		bit1.add(i,a[i]); bit2.add(i,1LL*a[i]*i);
    	}
    	seg.build(1,1,n);
    	while (m--)
    	{
    		int type,x,y;
    		scanf("%d%d%d",&type,&x,&y);
    		if (type==1) bit1.add(x,y),bit2.add(x,1LL*y*x),a[x]+=y;
    		if (type==2) bit1.add(x,-y),bit2.add(x,-1LL*y*x),a[x]-=y;
    		if (type==3) seg.update(1,x,y,1);
    		if (type==4) seg.update(1,x,y,0);
    		
    		ll sum=(bit1.query(n)+1)>>1;
    		int p=bit1.binary(sum);
    		int cnt=seg.query(1,1,p);
    		int pos1=seg.binary(1,cnt),pos2=seg.binary(1,cnt+1);
    		if (pos1==-1) pos1=pos2;
    		if (pos2==-1) pos2=pos1;
    		if (pos1<0 && pos2<0) { printf("-1\n"); continue; }
    		ll s1=bit2.query(n)-bit2.query(pos1-1)-(bit1.query(n)-bit1.query(pos1-1))*pos1+bit1.query(pos1)*pos1-bit2.query(pos1);
    		ll s2=bit2.query(n)-bit2.query(pos2-1)-(bit1.query(n)-bit1.query(pos2-1))*pos2+bit1.query(pos2)*pos2-bit2.query(pos2);
    		if (s1<=s2) printf("%d\n",pos1);
    			else printf("%d\n",pos2);
    	}
    	return 0;
    }
    
  • 相关阅读:
    apache+tomcat分布式搭建
    maven 加入本地jar包
    一步一步搭建Jenkins环境
    缓存详解
    nginx配置文件注释
    mybatis like的用法
    Golang聊天室
    windows 10安装gensim、nltk
    理解矩阵乘法
    超赞的 Go 语言 INI 文件操作
  • 原文地址:https://www.cnblogs.com/stoorz/p/13803924.html
Copyright © 2011-2022 走看看