![]() Rating:978 | A题神水不解释。要注意的是题目给定的序列已经是有序的了。 B题维护总数,+x 的时候+1,-x的时候减一,如果遇见没出现过的-x则答案加一。动态维护每个操作后的总数的最大值。 C题dp。dp[i][j]表示利用前i个数组合成j的拼法数。则dp[i][j]=∑(dp[i-1][j-a[i]*k]) (k>=0 && j-a[k]>=0) D题。可以二分枚举i表示询问了前i个,每次枚举判断当前是否可以判断出有撒谎。如果有撒谎则往前查找,没有撒谎则往后查找。也可以用set动态维护每个区间搜索。复杂度都是O(nlogn) E题。从后往前预处理出每个位置以后的不同的数的个数。查询时候直接输出即可。 |
![]() Rating:978 | C题记忆化搜索和dp都可以,做DP可以先从记忆化搜索开始,比较好理解。 |
![]() Rating:978 | D题set解法
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<set>
#include<math.h>
using namespace std;
#define CIN(x) scanf("%d",&x)
#define FOR(i,n) for(i=0;i<(n);i++)
int A[200005];
set<int> s;
int main(){
int n,k,m,i,a;
s.clear();
CIN(n);
CIN(k);
CIN(a);
CIN(m);
FOR(i,m){
CIN(A[i]);
}
s.insert(0);
s.insert(n+1);
int ans=(n+1)/(a+1);
FOR(i,m){
s.insert(A[i]);
set<int>::iterator it=s.find(A[i]);
it++;
int r=*it;
it--;
it--;
int l=*it;
ans-=(r-l)/(a+1);
ans+=(r-A[i])/(a+1);
ans+=(A[i]-l)/(a+1);
if(ans<k) break;
}
if(i<m)
printf("%d\n",i+1);
else printf("-1\n");
return 0;
} |
![]() Rating:978 | D题二分 http://blog.csdn.net/nike0good/article/details/47319837 |