首页 > 其他分享 >P4587 [FJOI2016]神秘数

P4587 [FJOI2016]神秘数

时间:2023-02-24 13:46:54浏览次数:40  
标签:神秘 FJOI2016 log int sum P4587 每次 include 复杂度

首先对于数 \(a_i\) 和一个 \(sum\) 内被全部覆盖的区间,若 \(a_i\le sum\),那么可以将区间覆盖到 \(a_i+sum\),经典背包,不证明。

那么通过这个可以推出来一种暴力做法,每一次找到一个在 \(l\) 到 \(r\) 小于等于 \(sum\) 的数,将 \(sum\) 加上它,然后再找,初始 \(sum=1\)。

但是这样复杂度明显会非常高,考虑优化这个过程。

利用树状数组维护 \(l\) 到 \(r\) 的所有数,每次查询 \(sum\) 以内的所有数,进行累加,如果 \(sum\) 值发生了改变,再重复这个过程,直到不变为止。

可以很好的发现,每进行一次这个过程,\(sum\) 的值近似 \(\times2\),所以总共最多进行 \(\log(\max(a_i))\) 次就可以更新完毕,我们称这种过程叫做迭代,迭代是因为处理顺序的原因导致一次答不出来最优解,就进行多次枚举得出答案的过程。

但是复杂度仍然不乐观,复杂度的根源在于每次建树状数组需要花费大量时间,所以考虑能否可持久化,那就可以打可持久化线段树,但是这里选择更简单的方法。

考虑对询问进行前缀和处理,每次需要查询的是 \(1\) 到 \(r\) 小于等于 \(sum\) 的数与 \(1\) 到 \(l-1\) 小于等于 \(sum\) 的数。

那么有很多区间的询问是重合的,就可以离线处理了。

先每次标记询问的位置,然后从前往后遍历整个序列,维护树状数组,每次再更新询问所得到的值,结束遍历后用前缀和处理每次的答案,与之前答案作对比,如果被更新了,那么继续迭代,直到无数值更新后,答案就统计出来了。

时间复杂度:\(O(n\times\log(n)\times\log(\max(a_i)))\)。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#define int long long
using namespace std;
const int N=1e5+5;
int n,m,cnt,f[N],t[N],ans[N],sum[N],bef[N];
struct node
{
	int name,data;
}a[N];
int cmp(node fi,node se)
{
	return fi.data<se.data;
}
int cmp2(node fi,node se)
{
	return fi.name<se.name;
}
struct node2
{
	int name,l,r,sum;
}p[N];
int cmp3(node2 fi,node2 se)
{
	return fi.r<se.r;
}
int lowbit(int x)
{
	return x&(-x);
}
void update(int x,int k)
{
	while(x<=cnt)
	{
		f[x]+=k;
		x+=lowbit(x);
	}
}
int search(int x)
{
	int sum=0;
	while(x)
	{
		sum+=f[x];
		x-=lowbit(x);
	}
	return sum;
}
vector<int>lc[N],rc[N];
void diedai()
{
	memset(f,0,sizeof(f));
	for(int i=1;i<=m;i++)sum[i]=1;
	bool flag=0;
	for(int i=1;i<=n;i++)lc[i].clear(),rc[i].clear();
	for(int i=1;i<=m;i++)lc[p[i].l-1].push_back(p[i].name);
	for(int i=1;i<=m;i++)rc[p[i].r].push_back(p[i].name);
	for(int i=1;i<=n;i++)
	{
		update(a[i].data,t[a[i].data]);
		int len=lc[i].size();
		for(int j=0;j<len;j++)
		{
			int l=1,r=cnt;
			while(l<r)
			{
				int mid=(l+r+1)>>1;
				if(t[mid]<=p[lc[i][j]].sum)l=mid;
				else r=mid-1;
			}
			sum[lc[i][j]]-=search(l);
		}
		len=rc[i].size();
		for(int j=0;j<len;j++)
		{
			int l=1,r=cnt;
			while(l<r)
			{
				int mid=(l+r+1)>>1;
				if(t[mid]<=p[rc[i][j]].sum)l=mid;
				else r=mid-1;
			}
			sum[rc[i][j]]+=search(l);
		}
	}
	for(int i=1;i<=m;i++)
	{
		bef[i]=p[i].sum;
		if(sum[i]!=p[i].sum)flag=1;
		p[i].sum=sum[i];
	}
	if(flag)diedai();
}
signed main()
{
	freopen("niuniunum.in","r",stdin);
	freopen("niuniunum.out","w",stdout);
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)scanf("%lld",&a[i].data),a[i].name=i;
	sort(a+1,a+1+n,cmp);
	int bef=-1;
	for(int i=1;i<=n;i++)
	{
		if(a[i].data!=bef)cnt++,t[cnt]=a[i].data;
		bef=a[i].data;
		a[i].data=cnt;
	}
	sort(a+1,a+1+n,cmp2);
	for(int i=1;i<=n;i++)update(a[i].data,a[i].data);
	scanf("%lld",&m);
	for(int i=1;i<=m;i++)
	{
		p[i].name=i;
		scanf("%lld%lld",&p[i].l,&p[i].r);
		p[i].sum=1;
	}
	diedai();
	for(int i=1;i<=m;i++)printf("%lld\n",p[i].sum);
	return 0;
}
/*
8 6
1 2 3 4 5 17 1 99
1 5
2 5
1 6
1 7
1 8
3 8
*/

标签:神秘,FJOI2016,log,int,sum,P4587,每次,include,复杂度
From: https://www.cnblogs.com/gmtfff/p/p4587.html

相关文章

  • chatgpt 神秘代码`~~
    sk-nr26uukCA5AJwloAEb5WT3BlbkFJbWaEqKghSPBDK4XZ09y1sk-PkWLSy4sFhQlquFF9D4xT3BlbkFJ5F9h5xsXouF2Bqy0wGoVsk-vzFUoZR3frqqICTaoNJqT3BlbkFJo29KX24Z0FnpPnVE0YTGsk-ed6......
  • 【Vijos1264】神秘的咒语
    problemsolutioncodes#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>usingnamespacestd;constintM=505;intn,la,lb,a[M],b[M],ans=0;in......
  • Jenkins 和 Kubernetes 云上的神秘代理
    最近我们构建和部署服务的方式与原来相比简直就是突飞猛进,像那种笨拙的、单一的、用于构建单体式应用程序的方式已经是过去式了。我们努力了这么久,终于达到了现在的效果。现......
  • 朋友圈那串神秘字符背后的开源项目「GitHub 热点速览」
    ​如果你这周没刷到类似“npub1sg6plzptd64u62a878hep2kev88swjh3tw00gjsfl8f237...”的一串字符,那就说明本期GitHubTrending周榜的内容非常适合你。这是前推特创始......
  • 神秘算法 —— 线性基求交
    线性基求交:设\(A,B\)为两个线性基,\(V_A,V_B\)分别为其生成空间,则\(V_C=V_A\capV_B\)是一个线性空间,称\(A\)与\(B\)两个线性基的交为\(C\)。首先证明\(V_C\)......
  • BUUCTF 神秘龙卷风
    神秘龙卷风转转转,科学家用四位数字为它命名,但是发现解密后居然是一串外星人代码!!好可怕!注意:得到的flag请包上flag{}提交打开压缩包发现先是破密,然后得到密码:  ......
  • 新职场之道-破除认知,享受神秘
    破除认知,享受神秘前言:一直以来,我们不断的被教育:“建认知”,“扩展认知”,“突破边界”...殊不知,其实是在不断的在“束缚”自己,然后以“打破边界,提升认知”为快乐,称之为“成......
  • [山东神秘题]逆序对
    求长度为\(n\)的逆序对数为\(k\)的排列的个数。\(n,k\le100000\)Sol:\(\Theta(n^3)\)的dp是显然的,或许能多项式优化,不过有更简单的做法。我们设\(s_i\)表示以......
  • 揭开华为云CodeArts TestPlan启发式测试设计神秘面纱!​
    ​2019年12月20日,是美国波音公司新一代载人飞船Starliner“星际客机”,执行第一次飞行测试任务的重要日。按计划飞船在本次无人试飞中将与国际空间站对接,为宇航员送上圣诞礼......
  • 揭开华为云CodeArts TestPlan启发式测试设计神秘面纱!
    摘要:质量是产品的生死线。本文分享自华为云社区《​​揭开华为云CodeArtsTestPlan启发式测试设计神秘面纱!​​》,作者:华为云PaaS服务小智。2019年12月20日,是美国波音公司新......