codeforces #472(div 1)

B(two point)

题意:

  给出长度为n的非递减数组E[1..n],对于所有三元组(i,j,k),1<=i<j<k<=n且Ek-Ei<=U,我们需要计算出最大的(Ek-Ej)/(Ek-Ei)

  n<=1e5

分析:

  考虑枚举i和k,那么j一定是i+1

  容易发现k越靠右值越大,所以k是满足Ek-Ei<=U的最大的k

  于是two point就行了

C(思维)

题意:

  主角每天对河流水位进行标记,相同水位不重复标记。给定每天的在河流水位上的标记数,求最小的所有天的河流水位下的标记数之和。

  n<=1e5

分析:

  等价于我们要最小化每天的标记总数

  我们可以得到一些限制条件,f(i)>=f(i-1) f(i)>=m(i)+1

  我们可以先从前到后扫一遍得到f

  但有些问题,就是可能会发生标记数突变,即有两天标记数差值超过1

  所以我们只能从后向前将依次递增,最后得到正确的f(i)

  答案就是Σf(i)-m(i)-1

D(二维偏序)

题意:
  在一个数轴上有n个飞机,每个飞机都有个飞行速度和初始位置。风速的范围是[-w,w]

  若两架飞机i,j可以在某个风速下同时到达0号点,我们就计数一次

  问最后计数的结果是多少

  n<=1e5,w<=1e5

分析:

  我们考虑作出每架飞机的到达时间与风速的函数图像,一定是光滑的单调曲线

  如果两架飞机可以同时到达原点,那么就是两条曲线有交点,那就是(ta-ta')(tb-tb')<=0

  于是就变成了一个二维偏序计数的问题,直接BIT就行了

E(dp)

题意:

  有n个箱子,每个箱子都有一个高度,部分箱子是重要箱子,部分箱子是非重要箱子。

  你需要找个垒箱子的顺序,使得底面高度在[l,r]范围内的重要箱子个数最多。

  n<=10000,保证所有箱子的高度和<=10000

分析:

  容易发现一个性质,那就是在[l,r]内连续放置的箱子一定是从小到大垒的

  于是我们可以枚举在[l,r]内放连续的最小的x个重要箱子,然后其它箱子作为垒高度用的

  但是可能会在这x个重要箱子上再放一个比较高的箱子,答案会+1

  于是dp[j]表示凑出高度j最少需要多少个重要箱子,就可以根据dp[j]的值判断是否答案加1了

  时间复杂度O(nh)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=10000;
 4 struct wjmzbmr
 5 {
 6     int a,b;
 7     bool operator < (const wjmzbmr &x) const
 8     {
 9         if(b!=x.b) return b<x.b;
10         return a>x.a;
11     }
12 }a[maxn+5];
13 int dp[maxn+5];
14 int s[maxn+5];
15 int n,l,r,m;
16 int ans;
17 int main()
18 {
19     scanf("%d%d%d",&n,&l,&r);
20     for(int i=1;i<=n;++i) scanf("%d",&a[i].a);
21     for(int i=1;i<=n;++i) scanf("%d",&a[i].b);
22     sort(a+1,a+n+1);
23     for(int i=0;i<=maxn;++i) dp[i]=n+1;
24     for(int i=n;i>=1;--i) s[i]=s[i+1]+a[i].a;
25     for(int i=1;i<=n;++i) if(a[i].b==0) ++m;else break;
26     //for(int i=1;i<=n;++i) printf("%d %d\n",a[i].a,a[i].b);
27     dp[0]=0;
28     for(int i=1;i<=n;++i)
29     {
30         if(i>m)
31             for(int j=l;j+s[i]<=r;++j)
32                 if(dp[j]<=n)
33                     ans=max(ans,n-i+1+(dp[j]+m<i-1));
34         for(int j=r;j>=a[i].a;--j)
35             dp[j]=min(dp[j],dp[j-a[i].a]+a[i].b);
36     }
37     for(int j=l;j<=r;++j)
38         if(dp[j]<n-m) ans=max(ans,1);
39     printf("%d\n",ans);
40     return 0;
41 }
View Code

 

 

posted @ 2018-04-02 23:04  Chellyutaha  阅读(196)  评论(0编辑  收藏  举报