ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[cf720D]Slalom

2021-04-10 07:01:10  阅读:129  来源: 互联网

标签:le Slalom ne cf720D 端点 cases 障碍 define


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

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

对于某一条路径,令$a_{i}$为其经过第$i$行时的段,则合法当且仅当
$$
a_{1}=1且\forall 2\le i\le 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}}]\ne \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}=\begin{cases}0&(a_{i}不存在)\\
f_{i-1,j}&(l_{i,a_{i}}\ne 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}=\begin{cases}0&((a_{i}不存在)\and (a_{i-1}存在))\\
f_{i-1,j}&((a_{i}和a_{i-1}都不存在)\or (l_{i,a_{i}}\ne 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}}\ne j))\end{cases}
$$
考虑用线段树维护当前$f_{i-1}$这个长为$n$的序列,那么仅需要修改第1类和第3类的位置

用set来维护障碍(直接维护所有$y_{1}\le i\le 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+k\log 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

 

标签:le,Slalom,ne,cf720D,端点,cases,障碍,define
来源: https://www.cnblogs.com/PYWBKTDA/p/14639473.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有