NOIP模拟题 2015.8.1 T2
NOIP模拟题 2015.8.2 T1

NOIP模拟题 2015.8.2 T3

HJWJBSR posted @ 2015年8月16日 22:16 in 题解 , 510 阅读

题解:有一个暴力是将r-l+1个数排序之后从小到大加,设已经加的数的和为s,当前要加ai,如果s<ai-1则不能加s(然而这个我在考场上面都没想到)于是正解就是优化一下,考虑每次加数把可以加的都加进来,于是s每次扩大一倍,至于加哪些数可以用主席树,复杂度为n log^2 n。

#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 100050
#define M 1073741824
int gf[N],st=0,s[N*50],c[N*50][2],v[N],n,m;
inline int Read()
 {
 	int x=0;char y;
 	do y=getchar(); while (y<'0'||y>'9');
 	do x=x*10+y-'0',y=getchar(); while (y>='0'&&y<='9');
 	return x;
 }
int Set_up(int x,int y,int z,int o)
 {
 	int i=x + y >> 1,j=++st;
 	if (x==y) {s[j]=s[z]+o;return j;}
    if (o<=i) c[j][1]=c[z][1],c[j][0]=Set_up(x,i,c[z][0],o);else
 	  c[j][0]=c[z][0],c[j][1]=Set_up(i+1,y,c[z][1],o);
 	s[j]=s[c[j][0]]+s[c[j][1]];
 	return j;
 }
int Find(int x,int y,int z,int o,int p,int u)
 {
 	int i=x + y >> 1,j=0;
 	if (x==p&&y==u) return s[o]-s[z];
 	if (p<=i) j=Find(x,i,c[z][0],c[o][0],p,min(u,i));
 	if (u>i) j+=Find(i+1,y,c[z][1],c[o][1],max(p,i+1),u);
 	return j;
 }
int Solve(int y,int x)
 {
 	int k=0,l=0,q=0;
 	do
 	 {
 	 	l=Find(0,M-1,gf[x-1],gf[y],q+1,k+1);
 	 	if (!l) return k+1;
 	 	q=k+1;k=k+l;
 	 } while (1);
 }
int main()
 {
 	freopen("hhsum.in","r",stdin);
 	freopen("hhsum.out","w",stdout);
 	n=Read();
 	for (int i=1;i<=n;i++) v[i]=Read();
 	for (int i=1;i<=n;i++)
 	  gf[i]=Set_up(0,M-1,gf[i-1],v[i]);
 	m=Read();
 	while (m--)
 	  printf("%d\n",Solve(Read(),Read()));
 	return 0;
 }

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter