zoukankan      html  css  js  c++  java
  • CF 338E, 线段树

    这道题真是太伤节奏了,做完之后好几天没动弹了。

    题目大意:给你两个数组a、b,a长b短,对于以a每个位置开头与b等长的连续子序列,我们询问是否有这样一个匹配方式让子序列每个数和b中每个数一一对应相加且和大于给定的常数h。

    解:没有想明白,去看官解没弄懂出题人是怎么分块瞎搞的。搜了一下题解,发现有一个更巧妙的解法,首先我们对b排序不会影响到结果,然后对于某个数,他在排序后的b里的合法匹配方案一定是连续的一段,这样就转化成了线段问题。对于Bn(从小到大排序的B数组),我们可知必须子序列里有n个数和他匹配,对于Bn-1,必须至少有n-1个数(因为可以允许有一个数匹配不了,但是匹配到Bn 上),于是等价于给定的n个线段覆盖让每个位置上的线段数>1,>2,>3 ... >n,如果开头把每个位置数都设成-1,-2,-3...-n,那么就是问n线段覆盖上去之后是否存在最小值小于零的格子(有则说明没有合法匹配)。至此我们便把原问题转化成线段树可做的问题。

    我大概yy了一下,貌似这个做法不能推广到区间资源分配上,因为这个问题的特殊性在于他是一个萝卜一个坑,而且合法的线段一定是延伸到n的。

      1 #include <cstdio>
      2 #include <string>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <cstring>
      7 #include <complex>
      8 #include <set>
      9 #include <vector>
     10 #include <map>
     11 #include <queue>
     12 #include <deque>
     13 #include <ctime>
     14 
     15 using namespace std;
     16 
     17 const double EPS = 1e-8;
     18 
     19 #define ABS(x) ((x)<0?(-(x)):(x))
     20 #define SQR(x) ((x)*(x))
     21 #define MIN(a,b) ((a)<(b)?(a):(b))
     22 #define MAX(a,b) ((a)>(b)?(a):(b))
     23 
     24 #define LSON(x) ((x)<<1)
     25 #define RSON(x) (((x)<<1)+1)
     26 #define LOWBIT(x) ((x)&(-(x)))
     27 #define MAXS 1111
     28 #define MAXN 222222
     29 #define VOIDPOINT 0
     30 #define LL long long
     31 #define OO 214748364
     32 
     33 struct SegTree{
     34     int l[MAXN*4], r[MAXN*4], m[MAXN*4], minn[MAXN*4], lazy[MAXN*4];
     35     int gx, gy, gz;
     36     void set(int a = 0, int b = 0, int c = 0) {
     37         gx = a; gy = b; gz = c;
     38     }
     39     inline void updata(int kok) {
     40         minn[kok] = min(minn[LSON(kok)], minn[RSON(kok)]);
     41     }
     42     inline void pushDown(int kok) {
     43         if (l[kok] != r[kok]) {
     44             lazy[LSON(kok)] += lazy[kok];
     45             minn[LSON(kok)] += lazy[kok];
     46             lazy[RSON(kok)] += lazy[kok];
     47             minn[RSON(kok)] += lazy[kok];
     48         }
     49         lazy[kok] = 0;
     50     }
     51     void build(int kok, int ll, int rr) {
     52         l[kok] = ll; r[kok] = rr; lazy[kok] = 0;
     53         if (ll == rr) {
     54             minn[kok] = -ll;
     55             return ;
     56         }
     57         int mid = m[kok] = (ll + rr) >> 1;
     58         build(LSON(kok), ll, mid); build(RSON(kok), mid+1, rr);
     59         updata(kok);
     60     }
     61     void insert(int kok) {
     62         if (gx > gy) return ;
     63         if (gx <= l[kok] && r[kok] <= gy) {
     64             lazy[kok] += gz; minn[kok] += gz;
     65             pushDown(kok);
     66             return ;
     67         }        
     68         if (lazy[kok])
     69             pushDown(kok);
     70         int mid = m[kok];
     71         if (gx <= mid) insert(LSON(kok));
     72         if (gy > mid) insert(RSON(kok));
     73         updata(kok);
     74     }    
     75 } Tree;
     76 
     77 int a[MAXN], b[MAXN], n, len, h;
     78 
     79 int main() {
     80 //    freopen("test.txt", "r", stdin);
     81 
     82     scanf("%d%d%d", &n, &len, &h);
     83     for (int i = 1; i <= len; ++i) scanf("%d", &b[i]);
     84     sort(b+1, b+1+len);
     85     Tree.build(1, 1, len);
     86     int ans = 0;
     87     for (int i = 1; i <= n; ++i) {
     88         scanf("%d", &a[i]); a[i] = h - a[i];
     89         a[i] = lower_bound(b+1, b+1+len, a[i]) - b;
     90         if (i < len) {
     91             Tree.set(a[i], len, 1);
     92             Tree.insert(1);
     93         }
     94     }
     95     for (int i = len; i <= n; ++i) {
     96         Tree.set(a[i], len, 1);
     97         Tree.insert(1);
     98         ans += Tree.minn[1] >= 0 ? 1: 0;
     99         Tree.set(a[i-len+1], len, -1);
    100         Tree.insert(1);
    101     }
    102     printf("%d
    ", ans);
    103     return 0;
    104 }
    CF 338E

    附上官解页面,以后有空要搞搞明白别人是怎么分块乱搞的:http://codeforces.com/blog/entry/8629

  • 相关阅读:
    leetcode131分割回文串
    leetcode315 计算右侧小于当前元素的个数
    Tensorflow写代码流程&反向传播
    vue脚手架的搭建
    Vue 脱坑记
    简历中的工作经历要怎么写?
    如何制作高水平简历?
    window.location.hash的知识点
    前端面试题小集
    前端面试题
  • 原文地址:https://www.cnblogs.com/wmzisfoolish/p/5696243.html
Copyright © 2011-2022 走看看