¿

n不超过20万，于是将读入的矿产质量离散化，主席树维护到每个位置时前缀质量个数的情况以及价值的情况。

#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int N=200010,M=20000010;
int n,m,maxx,fir[N],lst[N];
int T[N],L[M],R[M],tot,num[M];
ll ans1,ans2,s,sum[M];
char ch=getchar();
int val=0;
for(;(ch<'0')||(ch>'9');ch=getchar());
for(;(ch>='0')&&(ch<='9');val=val*10+ch-'0',ch=getchar());
return val;
}
struct thing{
int w,v;
}thi[N];
int c[N],cnt;
struct node{
int num;
ll sum;
node(int x=0,ll y=0){
num=x,sum=y;
}
};
void build(int &p,int l,int r){
if(!p)p=++tot;
if(l==r)return;
int mid=(l+r)/2;
build(L[p],l,mid);
build(R[p],mid+1,r);
}
void ins(int &p,int p0,int l,int r,int pos,int val){
p=++tot;
num[p]=num[p0]+1,sum[p]=sum[p0]+val;
L[p]=L[p0],R[p]=R[p0];
if(l==r)return;
int mid=(l+r)/2;
if(pos<=mid)ins(L[p],L[p0],l,mid,pos,val);
else ins(R[p],R[p0],mid+1,r,pos,val);
}
node query(int p,int p0,int l,int r,int pos){
if(pos<=l){
return node(num[p]-num[p0],sum[p]-sum[p0]);
}
int mid=(l+r)/2;
if(pos>mid)return query(R[p],R[p0],mid+1,r,pos);
else{
node val1=query(L[p],L[p0],l,mid,pos);
node val2=query(R[p],R[p0],mid+1,r,pos);
return node(val1.num+val2.num,val1.sum+val2.sum);
}
}
ll work(int x){
ll val=0;
for(int i=1;i<=m;i++){
node ans=query(T[lst[i]],T[fir[i]-1],1,200000,x);
val+=ans.num*ans.sum;
}
return val;
}
int main()
{
//    freopen("1.in","r",stdin);
scanf("%lld",&s);
build(T[0],1,200000);
for(int i=1;i<=n;i++){
c[++cnt]=thi[i].w;
maxx=max(maxx,thi[i].w);
}
sort(c+1,c+cnt+1);
cnt=unique(c+1,c+cnt+1)-c-1;
for(int i=1;i<=n;i++){
thi[i].w=lower_bound(c+1,c+cnt+1,thi[i].w)-c;
ins(T[i],T[i-1],1,200000,thi[i].w,thi[i].v);
}
for(int i=1;i<=m;i++){
}
int l=1,r=maxx;
while(l<=r){
int mid=(l+r)/2;
ll val1=work(mid);
if(val1==s){
printf("0\n");
return 0;
}
if(val1>s){
ans1=val1;
l=mid+1;
}
else{
ans2=val1;
r=mid-1;
}
}
if(ans1-s>s-ans2){
printf("%lld\n",s-ans2);
}
else printf("%lld\n",ans1-s);
return 0;
}

posted on 2019-11-14 20:13  Chloris_Black  阅读(59)  评论(0编辑  收藏