首先考虑,对于前十八个点,我们只需要暴力去查找,去算,这样复杂度是的。可以拿到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。。