首先考虑,对于前十八个点,我们只需要暴力去查找,去算,这样复杂度是的。可以拿到28.57~34.29的好成绩。
考虑满分做法,我们可以将通过不了的分成三类,如图:
上面的是JOI官方给的图片
第一类是OI小于a的,总分大于c的,第二类是Math小于b的,总分大于c的,第三类是总分小于c的。
很显然,c可以转化成max(c,a+b),因为如果a+b都没有到,说明一定有一科不及格。
回到上面的图,你发现了什么?
显然第一个条件和第二个条件是只能满足一个的,因为如果都满足那么OI和Math一定都不及格,而这不符合任意一个。
我们可以维护两个树状数组,分别记录OI和Math。我们发现只要不满足总分不小于c,那么是一定不合格的,我们只需要检查c,如果发现总分小于c就将小于的从两个树状数组里删掉。
我们可以用lower_bound来实现查找小于c的,到底有多少个。
于是我们就做完了,复杂度显而易见,是O(NlogNlogN)的,第一个log是树状数组的,而第二个log是lower_bound的。
MY CODE:
#include <iostream>
#include <algorithm>
#include <cmath>
#define pus push_back
#define pai pair<int,int>
#define fir first
#define sec second
#define M 1000005
#define Q 1000005
using namespace std;
int n,f,jsq=0;
pai p[M];
int v[M];
int a[Q];
bool cmp(pai x,pai y)
{
return x.fir+x.sec<y.fir+y.sec;
}
struct nod{
int a,b,c;
int d;
}q[Q];
bool compare(nod x,nod y)
{
return x.c<y.c;
}
int lob(int x)
{
return lower_bound(v+1,v+jsq+1,x)-v;
//STL algorithm
}
struct h{
int t[M*2];
int s;
int lowbit(int x)
{
return x&(-x);
}
void ins(int x,int y)
{
while(x<=s)
{
t[x]+=y;
x+=lowbit(x);
}
}
int query(int x)
{
int ans=0;
while(x>0)
{
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
//树状数组模板
}t[2];
int main()
{
cin>>n>>f;
for(int i=1;i<=n;i++)
{
cin>>p[i].fir>>p[i].sec;
v[++jsq]=p[i].fir;
v[++jsq]=p[i].sec;
//iostream自带pair
}
sort(v+1,v+jsq+1);
//STL algorithm
jsq=unique(v+1,v+jsq+1)-v-1;
//STL algorithm
t[0].s=t[1].s=jsq;
sort(p+1,p+n+1,cmp);
for(int i=1;i<=f;i++)
{
cin>>q[i].a>>q[i].b>>q[i].c;
q[i].c=max(q[i].c,q[i].a+q[i].b);
q[i].d=i;
a[i]=n;
}
sort(q+1,q+f+1,compare);
//STL algorithm
for(int i=1;i<=n;i++)
{
t[0].ins(lob(p[i].fir),1);
t[1].ins(lob(p[i].sec),1);
}
int ans=0;
for(int i=1;i<=f;i++)
{
while(ans<n&&p[ans+1].fir+p[ans+1].sec<q[i].c)
{
ans++;
t[0].ins(lob(p[ans].fir),-1);
t[1].ins(lob(p[ans].sec),-1);
}
a[q[i].d]-=ans;
a[q[i].d]-=t[0].query(lob(q[i].a)-1);
a[q[i].d]-=t[1].query(lob(q[i].b)-1);
}
for(int i=1;i<=f;i++)
cout<<a[i]<<endl;
return 0;
} 这一道题,已经把我折磨够了,后两体再补吧awa。。

京公网安备 11010502036488号