NKOJ 3777 卡牌操作(线段树)
来源:互联网 发布:怎么成为数据库管理员 编辑:程序博客网 时间:2024/05/20 12:50
P3777卡牌操作
问题描述
有n张卡片在桌上一字排开,每张卡片上有两个数,第i张卡片上,正面的数为a[i],反面的数为b[i]。现在,有m个熊孩子来破坏你的卡片了! 第i个熊孩子会交换c[i]和d[i]两个位置上的卡片。 每个熊孩子捣乱后,你都需要判断,通过任意翻转卡片(把正面变为反面或把反面变成正面,但不能改变卡片的位置),能否让卡片正面上的数从左到右单调不降。
输入格式
第一行一个n。接下来n行,每行两个数a[i],b[i]。接下来一行一个m。接下来m行,每行两个数c[i],d[i]。
输出格式
m行,每行对应一个答案。如果能成功,输出TAK,否则输出NIE。
样例输入
42 53 46 32 723 41 3
样例输出
NIETAK
提示
【样例解释】交换3和4后,卡片序列为(2,5) (3,4) (2,7) (6,3),不能成功。交换1和3后,卡片序列为(2,7) (3,4) (2,5) (6,3),翻转第3张卡片,卡片的正面为2,3,5,6,可以成功。n≤200000,m≤1000000,0≤a[i],b[i]≤10000000,1≤c[i],d[i]≤n.
首先用图论的思想,将一个卡牌看成两个点
那么是否有解的问题就变成了问是否存在一条路径可以从1走到n。
然后用到线段树维护连通性。
我们讨论一个区间
那么我们ls为区间的左儿子,rs为右儿子,那么我们需要考虑是否能通过左右儿子的值来算出
首先我们考虑算出
那么如果
否则讨论
如果都不满足,那么mid不能连到mid+1,意味着不存在一条从
最后只需要看
关于修改显然就是单点修改了。具体可以参考代码。
代码:
#include<stdio.h>#include<iostream>#include<algorithm>#define N 222222#define M 2222222using namespace std;int n,A[N],B[N],m;int ls[M],rs[M],va[M],vb[M],tot;void UD(int p,int l,int r){ int mid=(l+r>>1)+1; if(va[ls[p]]<=A[mid])va[p]=va[rs[p]]; else if(va[ls[p]]<=B[mid])va[p]=vb[rs[p]]; else va[p]=1e9; if(vb[ls[p]]<=A[mid])vb[p]=va[rs[p]]; else if(vb[ls[p]]<=B[mid])vb[p]=vb[rs[p]]; else vb[p]=1e9;}int BT(int x,int y){ int p=++tot; if(x<y) { int mid=x+y>>1; ls[p]=BT(x,mid); rs[p]=BT(mid+1,y); UD(p,x,y); } else va[p]=A[x],vb[p]=B[x]; return p;}void CHA(int p,int l,int r,int k){ if(l==r){va[p]=A[l];vb[p]=B[l];return;} int mid=l+r>>1; if(k<=mid)CHA(ls[p],l,mid,k); else CHA(rs[p],mid+1,r,k); UD(p,l,r);}int main(){ int i,x,y; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d%d",&A[i],&B[i]); if(A[i]>B[i])swap(A[i],B[i]); } BT(1,n); scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); swap(A[x],A[y]); swap(B[x],B[y]); CHA(1,1,n,x); CHA(1,1,n,y); if(va[1]!=1e9||vb[1]!=1e9)puts("TAK"); else puts("NIE"); }}
阅读全文
0 0
- NKOJ 3777 卡牌操作(线段树)
- NKOJ-3777 卡牌操作
- NKOJ 4254 区间MEX (线段树)
- NKOJ 3423 (NOI 2015) 软件包管理器 (树链剖分+线段树)
- NKOJ 2182 (HEOI 2012) 采花(树状数组/线段树)
- NKOJ 4000 (AHOI 2013)差异(后缀自动机/后缀数组+线段树/单调队列)
- 【题】【(堆/线段树/树状数组优化DP)/图论】NKOJ 3485 数据
- NKOJ 4090 找相同子串(后缀自动机/后缀数组+线段树)
- 【题】【线段树】NKOJ 1317 校门外有很多树
- 【趣题】【"竖着的"线段树】NKOJ 3726 史上最大值
- NKOJ-3768 数列操作
- NKOJ-3775 数列操作
- NKOJ 3768 数列操作(单调队列/栈+DP)
- NKOJ 3775 数列操作(单调队列+DP)
- 操作格子(线段树)
- 操作格子(线段树)
- 操作格子(线段树)
- 序列操作(线段树)
- Integer.bitCount()理解
- ef的多表联查
- CCF201703-2 学生排队
- 子线程怎么传递数据给主线程
- R语言 绘制热图 pheatmap
- NKOJ 3777 卡牌操作(线段树)
- textContent和innerText属性的区别
- 快速排序 C++
- wpf的小问题实记1---TextBox无法拖入事件
- python备忘六:list 列表之列表基本特性
- 安卓书籍--从入门到精通
- Jupyter Notebook的快捷键帮助文档
- 第二周项目一
- 群体运动度量--Measuring Crowd Collectiveness