ICode9

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

[unknown OJ] ZZH与背包

2020-12-02 10:01:46  阅读:208  来源: 互联网

标签:q2 OJ int unknown 复杂度 40 read ZZH id


一、题目

点此看题

二、解法

一看就是折半搜索,但是左边要排序右边要二分的, O ( 2 20 × q log ⁡ ) O(2^{20}\times q\log) O(220×qlog)

这种题往往就是卡掉排序的复杂度,我们可以考虑用归并排序来卡。

假设我们维护的是一个有序数组,那么我们加一个 v v v 的时候这个数组就变成了两个。一个是原来的数组,一个是每个元素都加上了 v v v 的数组,那么这两个数组就可以用归并,所以第一部分的复杂度变成 O ( 2 s ) O(2^s) O(2s)

第二部分其实也可以用归并,一共有 q 2 n − s q2^{n-s} q2n−s 个询问,每次加入一个 v v v 时可以用相同的方法归并起来,复杂度是 O ( q 2 n − s ) O(q2^{n-s}) O(q2n−s),然后我们用一个指针就可以一次处理所有询问。

那么当 2 s = q 2 40 2^s=\sqrt{q2^{40}} 2s=q240 ​ 时最优,时间复杂度是 O ( q 2 40 ) O(\sqrt{q2^{40}}) O(q240 ​),为了卡空间我干了一些好事

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std; 
#define int long long
const int M = (1<<25)+5;
const int K = 1e14;
const int K2 = 1e18;
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,m,k,q,o,a[M],b[M],c[M],p[M],v[45],ans[505];
struct node
{
	int x,id,fl;
	node(int X=0,int I=0,int F=0) : x(X) , id(I) , fl(F) {}
	bool operator < (const node &b)
	{
		return x<b.x;
	}
}s[1005];
void merge(int *a,int *b,int &m1,int m2)
{
	int i=1,j=1,t=0;
	while(i<=m1 && j<=m2)
	{
		if(a[i]%K<=b[j]%K) c[++t]=a[i],i++;
		else c[++t]=b[j],j++;
	}
	while(i<=m1) c[++t]=a[i],i++;
	while(j<=m2) c[++t]=b[j],j++;
	m1=t;
	for(int i=1;i<=m1;i++)
		a[i]=c[i];
}
signed main()
{
	n=read();q=o=read();
	k=min(25ll,n);
	for(int i=1;i<=n;i++)
		v[i]=read();
	a[++m]=0;
	for(int i=1;i<=k;i++)
	{
		for(int j=1;j<=m;j++)
			b[j]=a[j]+v[i];
		merge(a,b,m,m);
	}
	for(int i=1;i<=q;i++)
	{
		int l=read()-1,r=read();
		s[2*i-1]=node(l,i,K2);
		s[2*i]=node(r,i,0);
	}
	q=q<<1;
	sort(s+1,s+1+q);
	for(int i=1;i<=q;i++)
		p[i]=s[i].x+K*s[i].id+s[i].fl;
	for(int i=k+1;i<=n;i++)
	{
		int t=0;
		for(int j=1;j<=q;j++)
			if((p[j]%K)-v[i]>=0)
				b[++t]=p[j]-v[i];
		merge(p,b,q,t);
	}
	for(int i=1,j=1;i<=q;i++)
	{
		while(j<=m && (p[i]%K)>=a[j]) j++;
		int id=(p[i]%K2)/K,tg=p[i]/K2;
		if(tg) ans[id]-=(j-1);
		else ans[id]+=(j-1);
	}
	for(int i=1;i<=o;i++)
		printf("%lld\n",ans[i]);
}

标签:q2,OJ,int,unknown,复杂度,40,read,ZZH,id
来源: https://blog.csdn.net/C202044zxy/article/details/110468587

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

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

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

ICode9版权所有