• [cf720D]Slalom


    对于每一行,这些障碍将其划分为若干段,记第$i$行($y=i$时)从左到右第$j$段为$[l_{i,j},r_{i,j}]$

    显然一条路径恰好经过每一行中的一段,且两种方案不同当且仅当其中经过的一段不同

    对于某一条路径,令$a_{i}$为其经过第$i$行时的段,则合法当且仅当
    $$
    a_{1}=1且forall 2le ile n,[max_{j=1}^{i-1}l_{j,a_{j}},r_{i-1,a_{i-1}}]cap [l_{i,a_{i}},r_{i,a_{i}}] e empty
    $$
    且两种方案不同当且仅当$a_{i}$不同,题目即变为统计$a_{i}$的方案

    考虑dp统计,令$f_{i,j}$表示仅考虑$a_{1},a_{2},...,a_{i}$,满足$max_{k=1}^{i}l_{k,a_{k}}=j$且合法(仅考虑确定的部分)的方案数,初始状态由于强制$a_{1}=1$,即$f_{1,1}=1$

    同时有交的条件,也就保证了$max_{j=1}^{i}l_{j,a_{j}}$恰好在$a_{i}$所在段中,即通过$j$即可确定$a_{i}$

    由此,就可以得到暴力转移的式子,即
    $$
    f_{i,j}=egin{cases}0&(a_{i}不存在)\
    f_{i-1,j}&(l_{i,a_{i}} e j)\sum_{j'=l_{i-1,a_{i-1}}}^{j}f_{i-1,j'}&(l_{i,a_{i}}=j)end{cases}
    $$
    (其中$a_{i}$和$a_{i-1}$分别为第$i$和$i-1$行包含$j$的段编号)

    我们简单的对其更进一步的讨论,即找出所有满足$f_{i,j}=f_{i-1,j}$的情况都分入第2类,即
    $$
    f_{i,j}=egin{cases}0&((a_{i}不存在)and (a_{i-1}存在))\
    f_{i-1,j}&((a_{i}和a_{i-1}都不存在)or (l_{i,a_{i}} e j)and (l_{i-1,a_{i-1}}=j))\sum_{j'=l_{i-1,a_{i-1}}}^{j}f_{i-1,j'}&((l_{i,a_{i}}=j)and (l_{i-1,a_{i-1}} e j))end{cases}
    $$
    考虑用线段树维护当前$f_{i-1}$这个长为$n$的序列,那么仅需要修改第1类和第3类的位置

    用set来维护障碍(直接维护所有$y_{1}le ile y_{2}$的区间$[x_{1},x_{2}]$),差分的插入和删除

    对于第1类,这些位置必然被所有新插入障碍的区间包含(虽然这些区间可能之前也有障碍,但这样的数量级已经可以保证),总次数显然为$o(k)$

    对于第3类,也必然是新插入的障碍的$x+1$的位置(其中$x$为插入障碍的右端点)且未被障碍覆盖,在set中找到左端点小于等于$x+1$中最大的的右端点$x'$,对$[x'+1,x+1]$求和作为$f_{i,x+1}$即可

    (特别的,当不存在这样的区间时,令$x'$为0)

    但找到$x'$事实上比较困难,可能需要手写平衡树,注意到被障碍覆盖的位置$f$一定是0,因此$x'$只需要满足$[x'+1,x+1]$这一段仅有一个后缀(可以为空)无障碍即可

    那么只需要选择左端点小于等于$x$中最大的左端点所对应的右端点作为$x'$即可

    (另外需要记录答案统一修改,防止修改和查询之间相互影响)

    最终的答案不是$sum_{i=1}^{n}f_{m,i}$,而是要对找到右端点最大的障碍来统计,同样的原因也可以选左端点最大的右端点来计算

    总复杂度即为$o(m+klog n)$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 1000005
     4 #define mod 1000000007
     5 #define L (k<<1)
     6 #define R (L+1)
     7 #define mid (l+r>>1)
     8 #define fi first
     9 #define se second
    10 vector<pair<int,int> >v,v_add[N],v_del[N];
    11 multiset<pair<int,int> >s;
    12 multiset<pair<int,int> >::iterator it;
    13 int n,m,k,f[N<<2],tag[N<<2];
    14 void upd(int k){
    15     tag[k]=1;
    16     f[k]=0;
    17 }
    18 void up(int k){
    19     f[k]=(f[L]+f[R])%mod;
    20 }
    21 void down(int k){
    22     if (tag[k]){
    23         upd(L);
    24         upd(R);
    25         tag[k]=0;
    26     }
    27 }
    28 void update_val(int k,int l,int r,int x,int y){
    29     if (l==r){
    30         f[k]=y;
    31         return;
    32     }
    33     down(k);
    34     if (x<=mid)update_val(L,l,mid,x,y);
    35     else update_val(R,mid+1,r,x,y);
    36     up(k);
    37 }
    38 void update_zero(int k,int l,int r,int x,int y){
    39     if ((l>y)||(x>r))return;
    40     if ((x<=l)&&(r<=y)){
    41         upd(k);
    42         return;
    43     }
    44     down(k);
    45     update_zero(L,l,mid,x,y);
    46     update_zero(R,mid+1,r,x,y);
    47     up(k);
    48 }
    49 int query(int k,int l,int r,int x,int y){
    50     if ((l>y)||(x>r))return 0;
    51     if ((x<=l)&&(r<=y))return f[k];
    52     down(k);
    53     return (query(L,l,mid,x,y)+query(R,mid+1,r,x,y))%mod;
    54 }
    55 int main(){
    56     scanf("%d%d%d",&n,&m,&k);
    57     update_val(1,1,n,1,1);
    58     for(int i=1;i<=k;i++){
    59         int x1,y1,x2,y2;
    60         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    61         v_add[y1].push_back(make_pair(x1,x2));
    62         if (y2<m)v_del[y2+1].push_back(make_pair(x1,x2));
    63     }
    64     for(int i=1;i<=m;i++){
    65         v.clear();
    66         for(int j=0;j<v_add[i].size();j++){
    67             int x=v_add[i][j].se+1;
    68             if ((i>1)&&(x<=n)){
    69                 it=s.lower_bound(make_pair(x+1,0));
    70                 int xx=1;
    71                 if (it!=s.begin())xx=(*--it).se+1;
    72                 if (xx<x)v.push_back(make_pair(x,query(1,1,n,xx,x)));
    73             }
    74         }
    75         for(int j=0;j<v.size();j++)update_val(1,1,n,v[j].fi,v[j].se);
    76         for(int j=0;j<v_add[i].size();j++){
    77             s.insert(v_add[i][j]);
    78             update_zero(1,1,n,v_add[i][j].fi,v_add[i][j].se);
    79         }
    80         for(int j=0;j<v_del[i].size();j++)s.erase(s.find(v_del[i][j]));
    81     }
    82     if (s.size())printf("%d",query(1,1,n,(*--s.end()).se+1,n));
    83     else printf("%d",query(1,1,n,1,n));
    84 } 
    View Code
  • 相关阅读:
    mha 安装部署报错 failed: Attempt to reload DBD/mysql.pm aborted
    zabbix 不能触发动作产生告警
    zabbix 编译安装
    zabbix 解决中文乱码
    virtualbox 配置虚拟机能够和宿主机相互通信
    INCEPTION 编译过程报错 make[2]: * [sql/CMakeFiles/sql.dir/sql_yacc.cc.o] Error
    数据库运维平台
    mysql 归档工具 pt-archiver
    java面试基础篇
    非对称和对称加密结合
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14639473.html
Copyright © 2020-2023  润新知