您的位置:首页 > 其它

NOIP2011提高组 聪明的质检员

2016-08-01 12:02 337 查看


这道题很明显要用二分猜答案,猜w的值,再来check。这里我用的前缀和的方法来check,求出前i个大于w 的个数和价值和,然后枚举每一个区间,算就好了。

注:要注意用longlong(考试的时候我就是这个错了)。

具体程序如下:

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=200005;
struct shu
{
int w,v;
}a[maxn];
struct data
{
int x,y,id;
}b[maxn];
long long n,m,s,g[maxn][3];

long long read()
{
long long x=0,ok=0;
char ch;
ch=getchar();

while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
while((ch>='0'&&ch<='9')||ch=='-')
{
if(ch=='-') ok=1;
else x=x*10+ch-'0';
ch=getchar();
}

return ok==1?-x:x;
}
void init()
{
n=read();
m=read();
s=read();
for(int i=1;i<=n;i++)
{
a[i].w=read();
a[i].v=read();
}
for(int j=1;j<=m;j++)
{
b[j].x=read();
b[j].y=read();
}
}
long long check(long long x)
{
long long ans=0;
for(int i=1;i<=n;i++)
{
if(a[i].w>=x)
{
g[i][1]=g[i-1][1]+1;
g[i][0]=g[i-1][0]+a[i].v;
}
else
{
g[i][1]=g[i-1][1];
g[i][0]=g[i-1][0];
}
}
for(int i=1;i<=m;i++)
{
long long x1=g[b[i].y][1]-g[b[i].x-1][1];
long long x2=g[b[i].y][0]-g[b[i].x-1][0];
ans+=x1*x2;
}
return ans;
}
int main()
{
//freopen("qc.in","r",stdin);
//freopen("qc.out","w",stdout);
init();
int x=0,y=1000000;
long long ans=10000000000000000ll;
while(x<=y)
{
int z=(x+y)/2;
long long p=check(z);
if(p>s) x=z+1;
if(p<s) y=z-1;
if(p==s)
{
printf("0");
return 0;
}
ans=min(ans,abs(p-s));
}
cout<<ans;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: