# luogu1314聪明的质检员

1 、给定m 个区间[Li,Ri]；

2 、选出一个参数 W；

3 、对于一个区间[Li,Ri]，计算矿石在这个区间上的检验值Yi：

5 3 15
1 5
2 5
3 5
4 5
5 5
1 5
2 4
3 3

10

#include<cstdio>
#define N 220000
int x=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x;
}
struct node{
int l,r,left,right,sum1;long long sum2;int dfn;
}tree[N<<2];
int n,m,w[N],v[N],num,root,x[N],y[N];long long s;
inline int max(int x,int y){
return x>y?x:y;
}
long long abs(long long a,long long b){
if (a<=b) return b-a;else return a-b;
}
inline long long min(long long x,long long y){
return x<y?x:y;
}
inline void update(int x){
int l=tree[x].left,r=tree[x].right;
tree[x].sum1=tree[l].sum1+tree[r].sum1;
tree[x].sum2=tree[l].sum2+tree[r].sum2;
}
void build(int &x,int l,int r,int vv){
x=++num;tree[x].l=l;tree[x].r=r;
if (l==r){if (w[l]>=vv) tree[x].sum1=1,tree[x].sum2=v[l];else tree[x].sum1=tree[x].sum2=tree[x].left=tree[x].right=0;return;}
int mid=l+r>>1;
build(tree[x].left,l,mid,vv);build(tree[x].right,mid+1,r,vv);
update(x);
}
long long tmp1,tmp2;int cnt;
void query(int x,int l,int r){
if(!x) return;
if (l<=tree[x].l&&r>=tree[x].r){tmp1+=tree[x].sum1;tmp2+=tree[x].sum2;return;}
int mid=tree[x].l+tree[x].r>>1;
if (l<=mid) query(tree[x].left,l,r);
if (r>mid) query(tree[x].right,l,r);
}
void change(int &x,int l,int r,int p){
if (!x)x=++num;tree[x].l=l;tree[x].r=r;tree[x].dfn=cnt;if (tree[tree[x].left].dfn!=cnt) tree[x].left=0;if (tree[tree[x].right].dfn!=cnt) tree[x].right=0;
if (l==r){tree[x].sum1=1,tree[x].sum2=v[p]; tree[x].left=tree[x].right=0;return;}
int mid=l+r>>1;
if (p<=mid) change(tree[x].left,l,mid,p);else change(tree[x].right,mid+1,r,p);
update(x);
}
void print(int x){
if (tree[x].left) print(tree[x].left);
printf("%d %d %d %d\n",tree[x].l,tree[x].r,tree[x].sum1,tree[x].sum2);
if (tree[x].right) print(tree[x].right);
}
long long ans=1LL<<60;
inline long long  check(int xx){
num=0;root=0;cnt++;//build(root,1,n,xx);
for (int i=1;i<=n;++i)
{if (w[i]>=xx) change(root,1,n,i);}
//print(root);printf("check\n");
long long tmp=0;
for (int i=1;i<=m;++i){
tmp1=0,tmp2=0;
int x1=x[i],y1=y[i];query(root,x1,y1);tmp+=tmp1*tmp2;
if (tmp-s>=ans) return s+1;
}
ans=min(abs(s,tmp),ans);
return tmp;
}
int main(){
freopen("1314.in","r",stdin);
while (l<=r){
int mid=l+r>>1;long long tmpp=check(mid);
if (tmpp<=s) r=mid-1;else l=mid+1;
}
printf("%lld",ans);
return 0;
}

#include<cstdio>
#define N 220000
int x=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x;
}
int n,m,w[N],v[N],num,root,x[N],y[N],sum1[N];long long s,sum2[N];
inline int max(int x,int y){
return x>y?x:y;
}
long long abs(long long a,long long b){
if (a<=b) return b-a;else return a-b;
}
inline long long min(long long x,long long y){
return x<y?x:y;
}
long long ans=1LL<<60;
inline long long  check(int xx){
for(int i=1;i<=n;++i){
if (w[i]>=xx) sum1[i]=sum1[i-1]+1,sum2[i]=sum2[i-1]+v[i];else sum1[i]=sum1[i-1],sum2[i]=sum2[i-1];
}
long long tmp=0;
for (int i=1;i<=m;++i){
tmp+=(sum1[y[i]]-sum1[x[i]-1])*(sum2[y[i]]-sum2[x[i]-1]);
if (tmp-s>=ans) return s+1;
}
ans=min(abs(s,tmp),ans);
return tmp;
}
int main(){
freopen("1314.in","r",stdin);
while (l<=r){
int mid=l+r>>1;long long tmpp=check(mid);
if (tmpp<=s) r=mid-1;else l=mid+1;
}
printf("%lld",ans);
return 0;
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120