思路:n^2的做法,貪心,先按照價值升序排序,每次從ddl往前找空餘位置,如果能放進去,就標記一下,不然就放棄。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,t;
bool b[1001];
struct da{int t,x;}s[1001];
int cmp(const da &x,const da &y)
{
return x.x!=y.x?x.x>y.x:x.t>y.t;
}
int main()
{
// freopen("1.txt","r",stdin);
scanf("%d",&t);
while(t--)
{
int ans=0;
scanf("%d",&n);memset(b,0,sizeof b);
for(int i=1;i<=n;i++) scanf("%d",&s[i].t);
for(int i=1;i<=n;i++) scanf("%d",&s[i].x);
sort(s+1,s+n+1,cmp);
for(int i=1;i<=n;i++)
{
bool flag=false;
for(int j=s[i].t;j>=1;j--)
if(!b[j]) {b[j]=true,flag=true;break;}
if(!flag) ans+=s[i].x;
}
printf("%d\n",ans);
}
return 0;
}
總結:有點二位偏序的意思,只寫了n^2的做法,更優的做法的話可以考慮倒序枚舉,這樣可以降掉一維,然後用數據結構維護當前的max,每次取當前的最優值即可,因爲是動態的,所以用堆比較好寫一點。還有線段樹維護區間最右點的解法,在n ^ 2基礎上稍加改動即可。
思路:二分,n^2 log n^2 ,將ab合爲一個長度爲n^ 2的數組,cd也合爲一個長度爲n^2的數組,然後二分cd數組,計算複合條件的數。
#include<cstdio>
#include<algorithm>
#define MAXN 4001
using namespace std;
int n,tot,a[MAXN],b[MAXN],c[MAXN],d[MAXN],s[MAXN*MAXN];
int erfenr(int x)
{
x=-x;
int l=1,r=tot,ans=-1;
while(l<=r)
{
int mid=l+r>>1;
if(s[mid]==x) ans=mid,l=mid+1;
else if(s[mid]>x) r=mid-1;
else l=mid+1;
}
return ans;
}
int erfenl(int x)
{
x=-x;
int l=1,r=tot,ans=-1;
while(l<=r)
{
int mid=l+r>>1;
if(s[mid]>=x) ans=mid,r=mid-1;
else l=mid+1;
}
return ans;
}
int main()
{
int ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
s[++tot]=a[i]+b[j];
sort(s+1,s+tot+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
int l=erfenl(c[i]+d[j]);
int r=erfenr(c[i]+d[j]);
if(r==-1) continue;
ans+=r-l+1;
}
printf("%d",ans);
return 0;
}
總結:二分模板題,map會T,而且這題略卡常。
思路:二分答案。先按照a[i]升序排序,二分答案x,檢驗滿足 a[i]+x<=a[j]的對數tot,如果tot>中位數條件就 向左二分,反之向右。檢驗的時候二分查找,可以將條件改爲找大於a[i]+x的lower_bound,然後位置減一即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
int n,a[100001],ans;
int ffind(int x)
{
x++;
int l=1,r=n,mid,tot=n+1;
while(l<=r)
{
mid=l+r>>1;
if(a[mid]>=x) tot=mid,r=mid-1;
else l=mid+1;
}
return tot-1;
}
bool check(int x)
{
LL tot=0;
for(int i=1;i<=n;i++)
{
tot+=ffind(a[i]+x)-i;
}
return tot*2>=((n-1)*n+1)/2;
}
void erfen(int l,int r)
{
int mid;
while(l<=r){
mid=l+r>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
return ;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
ans=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
erfen(0,a[n]-a[1]);
printf("%d\n",ans);
}
return 0;
}
總結:思路不難想,有點細節沒處理好,導致寫了很久,以後要認真分析,不要急着碼(???老毛病又犯了)。