当前位置:首页 > 编程笔记 > 正文
已解决

【学习笔记】[PA2019] Osady i warownie 2

来自网友在路上 157857提问 提问时间:2023-11-04 18:50:12阅读次数: 57

最佳答案 问答题库578位专家为你答疑解惑

这题好抽象😱

EI 说这题可以转化为对偶图,但是我完全没看懂😅

考虑维护最向右和向下的两条路径,那么不能放的位置就是两条路径的交(感性理解一下)

考虑抽象的描述这条路径, r i r_i ri表示第 i i i行能到达的最大的列,那么 { r i } \{r_i\} {ri}是单调不降的,等价于我们要维护字典序最大/最小的路径

考虑向下的怎么维护。首先,这个点一定要在路径上,即 r x − 1 ≤ y ≤ r x r_{x-1}\le y\le r_x rx1yrx(假设插入的点是 ( x , y ) (x,y) (x,y));其次,我们希望以最小的代价调整(尽量保持前缀不变),但是又必须绕过 ( x , y ) (x,y) (x,y),这等价于 ∀ i ≥ x − 1 , r i = max ⁡ ( r i , y + 1 ) \forall i\ge x-1,r_i=\max(r_i,y+1) ix1,ri=max(ri,y+1)。注意到每次调整时至少有一个障碍以后不会被考虑到,因此总调整数目不会超过 O ( k ) O(k) O(k)

因此递归下去即可。

复杂度 O ( k log ⁡ k ) O(k\log k) O(klogk)

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
int n,m,K,v;
struct node{set<int>sx[100005],sy[100005];int bit[100005];int n,m;int get(int x,int y){return sx[x].count(y);}void add(int x,int y){for(x++;x<=n;x+=x&-x)bit[x]=max(bit[x],y);}int qmax(int x){int y(0);for(x++;x;x-=x&-x)y=max(y,bit[x]);return y;}int query(int x,int y){if(x==0)return qmax(x)>=y;return qmax(x-1)<=y&&y<=qmax(x);}void upd(int x,int y){if(!query(x,y))return;add(x-1,y+1),x--,y++;if(sx[x].size()&&sx[x].upper_bound(y)!=sx[x].begin()){auto it=--sx[x].upper_bound(y);upd(x,*it);}if(sy[y].size()&&sy[y].lower_bound(x)!=sy[y].end()){auto it=sy[y].lower_bound(x);upd(*it,y);}}void ins(int x,int y){sx[x].insert(y),sy[y].insert(x);upd(x,y);}
}R,D;
int main(){ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);cin>>n>>m>>K;D.n=n,D.m=m;R.n=m,R.m=n;D.add(n-1,m-1);R.add(m-1,n-1);for(int i=1;i<=K;i++){int r,c,z;cin>>r>>c>>z;r=(r^v)%n,c=(c^v)%m;if(D.get(r,c)){cout<<"NIE"<<"\n";}else if(D.query(r,c)&&R.query(c,r)){cout<<"TAK"<<"\n";v^=z;}   else{cout<<"NIE"<<"\n";D.ins(r,c),R.ins(c,r);}}
}
查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"【学习笔记】[PA2019] Osady i warownie 2":http://eshow365.cn/6-32078-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!