zoukankan      html  css  js  c++  java
  • 雅礼集训 part1


    2017


    Day1


    市场

    实际上算上区间加法增长的部分值域也很低, 对于区间整除最多做 log 次。

    所以直接线段树暴力维护。

    记录

    矩阵

    为什么我会默认可以用列给行染色啊?

    只能先搞出一行全黑,然后染完所有列。

    由于是给列染色,所以对于第 k 行,只要存在某一行的第 k 列是黑,就可以完成补色,且补色的步数一定。

    对于实现,考虑一下分支情况就很好做了。

    不想写(kel

    字符串

    (q imes k le 10^5)

    算法一:

    每次询问把 w 的所有的子串的 f 处理出来然后计算那个 Σ。

    可以莫队算那个 Σ, 也可以预处理后直接在处理 w 的子串的 f 的过程中算一下这个子串在 [a,b] 之间被提到的次数, 后者更好写。

    复杂度是 (O(qk^2log m))

    算法二:

    考虑预处理后直接计算 Σ。

    具体地, 对于每个 w 的每个 endpos, r,算出其最多往前延长到哪里,使得串是 S 的子串, 然后对于每个询问 f (,,l,r), 直接倍增在 parent 树上跳 fa 找到 w[l,r] 对应的节点即可。

    不倍增也能过?????

    复杂度 (O(qlog n(k+m)))

    记录


    Day2


    水箱

    考虑最优的答案对应的局面,整个水箱必定被划分成几段, 即 ([1,2,cdots,n]) 被划分成 ([1,cdots,k][k+1,cdots,p]cdots[s+1,n])

    对于相同段, 水位相同且挡板不高于水面, 对于不同段, 有挡板相隔, 相隔的定义是挡板两边的水位不同。

    考虑从低到高扫描最低水位, 在这个过程中对所有格子灌水使得所有格子的最低水位恰好为这个最低水位(大概), 水位高于挡板就合并连通块。在这个过程中,所有可能出现的段都会被观测到, 在观测的过程中统计答案, 每个段都要考虑最优的选择是当前水位还是历史上出现过的子段结构的组合。

    记录

    棋盘游戏

    将棋盘黑白染色后建二分图,从某点开始先手必胜当且仅当当前点在所有的最大匹配中都是匹配点, 证明略。

    找在某个最大匹配中不是匹配点的方法:首先求任意一个最大匹配,然后从所有非匹配点开始 dfs, 每次遍历与当前点相邻的点 v,v 一定有匹配边,对于与 v 匹配的点 u, dfs(u),给所有 dfs 到的点打上标记,所有打上标记的点都是要找的点。

    证明略。

    记录

    线段游戏

    李超树板子。以前写过几次,忘了,这里再整理一下。

    首先是存储,对于线段 (y = kx+b) , 存储 ((k,b))

    typedef pair<double,double> linE;

    有两个关于线段的函数:

    // 一次函数求值
    double f (linE l, int x) { return l.first * x + l.second; }
    // 求线段交点的横坐标
    double inter (linE x, linE y) {
      return (y.second - x.second) / (x.first - y.first);
    }
    

    插入逻辑自然,比较好写

    #define li (me << 1)
    #define ri (li | 1)
    #define mid ((l+r)>>1)
    #define ls li,l,mid
    #define rs ri,mid+1,r
    void ins (int me, int l, int r, int x, int y, int id) {
      if (l > r) return ;
      if (x <= l && r <= y) {
        if (! vis[me]) { vis[me] = true, t[me] = id; return ; }
        double ly1 = f (lin[id], l), ry1 = f (lin[id], r),
        ly = f (lin[t[me]], l), ry = f (lin[t[me]], r);
        if (ly1 <= ly && ry1 <= ry) return ;
        if (ly1 >= ly && ry1 >= ry) { t[me] = id; return ; }
        double in = inter (lin[id], lin[t[me]]);
        if (ly1 >= ly) {
          if (in <= mid) ins (ls, x, y, id);
          else ins (rs, x, y, t[me]), t[me] = id;
        } else {
          if (in > mid) ins (rs, x, y, id);
          else ins (ls, x, y, t[me]), t[me] = id;
        }
        return ;
      }
      if (x <= mid) ins (ls, x, y, id);
      if (y > mid) ins (rs, x, y, id);
    }
    

    删除逻辑也可, 写起来很舒服。

    int lccmp (int X, int x, int y) {
      if (!x || !y) return x | y;
      return f (lin[x], X) > f (lin[y], X) ? x : y;
    }
    int get (int me, int l, int r, int x) {
      int res = 0;
      if (vis[me]) res = t[me];
      if (l == r) return res;
      return lccmp (x, res, x <= mid ? get (ls, x) : get (rs, x));
    }
    

    记录

  • 相关阅读:
    Codeforces 798C. Mike and gcd problem 模拟构造 数组gcd大于1
    Codeforces 796C. Bank Hacking
    Codeforces 792B. Counting-out Rhyme
    gym 101164 H.Pub crawl 凸包
    hdu 6053 TrickGCD 筛法
    hdu 6041 I Curse Myself 无向图找环+优先队列
    bzoj 2243: [SDOI2011]染色 线段树区间合并+树链剖分
    codeforces gym 101164 K Cutting 字符串hash
    树链剖分求lca
    UESTC 1697 简单GCD问题(一) 筛法
  • 原文地址:https://www.cnblogs.com/tztqwq/p/14514673.html
Copyright © 2011-2022 走看看