ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2019 ICPC Asia Xuzhou Regional. H. Yuuki and a problem(树状数组套主席树)

2020-12-05 22:03:05  阅读:204  来源: 互联网

标签:log rs int Sum Regional Asia ICPC mx define


题目链接


\(Description\)
给定长为\(n\)的序列\(A_i\),两种操作:

  1. 将某个数\(A_i\)修改为\(v\)。
  2. 查询用区间\([l,r]\)内的数不能组成的最小的数(能组成\(v\)是指存在一个\([l,r]\)的子集\(s\)使\(s\)的和等于\(v\))。
    \(n,A_i\leq 2\times10^5\)。

\(Solution\)
BZOJ(CodeChef)原题树套树版/whl

先考虑询问。设区间\([l,r]\)内已经可以组成的数为\([1,v]\),\([l,r]\)中最小的大于\(v\)的数为\(mx\),若\(mx>v+1\)则区间的答案即为\(v+1\);否则\(mx=v+1\),\(v\)可以更新为\(Sum(1,v+1)\)(\([l,r]\)中值在\([1,v+1]\)的所有数的和),继续重复上述过程。
求\(mx\)的时候可以求\(Sum(1,v+1)\),若\(Sum=mx\)则显然\(mx>v+1\);否则\(mx=v+1\)。
容易发现\(v\)每次至少增加\(v+1\),且这个过程可以用主席树实现。所以查询复杂度为\(O(\log V\log n)\)。
对于修改,改成带修改主席树(树状数组套主席树)就可以了。复杂度\(O(n\log V\log^2n)\)。

这个带修改主席树,每个位置维护一个前缀和即可,查询是单点查询。(不太懂他们麻烦的写法/whl


//1144ms	486.4MB
#include <bits/stdc++.h>
#define pc putchar
#define gc() getchar()
typedef long long LL;
const int N=2e5+5,V=2e5;

int A[N];
struct President_Tree
{
	#define S N*155//N*18*18*2 //注意MLE。。
	#define ls son[x][0]
	#define rs son[x][1]
	#define lson ls,l,m
	#define rson rs,m+1,r
	int tot,son[S][2];
	LL pre[S];
	#define R(x) (rs?rs:(rs=++tot))
	void Insert(int &x,int l,int r,int p)
	{
		!x&&(x=++tot);
		if(l==r) {pre[x]+=l; return;}
		int m=l+r>>1; p<=m?(pre[R(x)]+=p,Insert(lson,p)):Insert(rson,p);
	}
	void Delete(int &x,int l,int r,int p)
	{
//		!x&&(x=++tot);
		if(l==r) {pre[x]-=l; return;}
		int m=l+r>>1; p<=m?(pre[R(x)]-=p,Delete(lson,p)):Delete(rson,p);
	}
	LL Query(int x,int l,int r,int p)
	{
		if(!x) return 0;
		if(l==r) return pre[x];
		int m=l+r>>1; return pre[x]+(p<=m?Query(lson,p):Query(rson,p));
	}
};
struct BIT
{
	President_Tree T;
	int n,root[N];
	std::vector<int> vl,vr;
	#define lb(x) (x&-(x))
	void Modify(int p,int a,int v)
	{
		for(; p<=n; p+=lb(p))
		{
			if(a) T.Delete(root[p],1,V,a);
			T.Insert(root[p],1,V,v);
		}
	}
	void Query0(int l,int r)
	{
		vl.clear(), vr.clear();
		for(int p=r; p; p^=lb(p)) vr.emplace_back(p);
		for(int p=l-1; p; p^=lb(p)) vl.emplace_back(p);		
	}
	LL Query(int v)
	{
		LL res=0;
		for(auto p:vr) res+=T.Query(root[p],1,V,v);
		for(auto p:vl) res-=T.Query(root[p],1,V,v);
		return res;
	}
}T;

inline int read()
{
	int now=0,f=1; char c=gc();
	for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
	for(;isdigit(c);now=now*10+c-48,c=gc());
	return now*f;
}

int main()
{
	int n=read(),Q=read(); T.n=n;
	for(int i=1; i<=n; ++i) A[i]=read();
	for(int i=1; i<=n; ++i) T.Modify(i,0,A[i]);
	for(int p,v; Q--; )
	{
		if(read()==1) p=read(),v=read(),T.Modify(p,A[p],v),A[p]=v;
		else
		{
			LL v=0; int l=read(),r=read(); T.Query0(l,r);//树状数组节点可以先求出来 
			while(1)
			{
				LL s=T.Query((int)std::min(LL(V),v+1));//不需要离散化 
				if(s==v) break;
				v=s;
			}
			printf("%lld\n",v+1);
		}
	}

	return 0;
}

标签:log,rs,int,Sum,Regional,Asia,ICPC,mx,define
来源: https://www.cnblogs.com/SovietPower/p/14091362.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有