BZOJ3526[Poi2014]Card——线段树合并
題目描述
有n張卡片在桌上一字排開(kāi),每張卡片上有兩個(gè)數(shù),第i張卡片上,正面的數(shù)為a[i],反面的數(shù)為b[i]?,F(xiàn)在,有m個(gè)熊孩子來(lái)破壞你的卡片了!
第i個(gè)熊孩子會(huì)交換c[i]和d[i]兩個(gè)位置上的卡片。
每個(gè)熊孩子搗亂后,你都需要判斷,通過(guò)任意翻轉(zhuǎn)卡片(把正面變?yōu)榉疵婊虬逊疵孀兂烧?#xff0c;但不能改變卡片的位置),能否讓卡片正面上的數(shù)從左到右單調(diào)不降。
輸入
第一行一個(gè)n。
接下來(lái)n行,每行兩個(gè)數(shù)a[i],b[i]。
接下來(lái)一行一個(gè)m。
接下來(lái)m行,每行兩個(gè)數(shù)c[i],d[i]。
輸出
m行,每行對(duì)應(yīng)一個(gè)答案。如果能成功,輸出TAK,否則輸出NIE。
樣例輸入
42 5
3 4
6 3
2 7
2
3 4
1 3
樣例輸出
NIETAK
提示
【樣例解釋】
交換3和4后,卡片序列為(2,5) (3,4) (2,7) (6,3),不能成功。
交換1和3后,卡片序列為(2,7) (3,4) (2,5) (6,3),翻轉(zhuǎn)第3張卡片,卡片的正面為2,3,5,6,可以成功。
【數(shù)據(jù)范圍】
n≤200000,m≤1000000,0≤a[i],b[i]≤10000000,1≤c[i],d[i]≤n.
?
線(xiàn)段樹(shù)合并好題。線(xiàn)段樹(shù)每個(gè)節(jié)點(diǎn)維護(hù)s[x][0/1][0/1],表示x節(jié)點(diǎn)對(duì)應(yīng)區(qū)間左/右端點(diǎn)選正/背面區(qū)間能否單調(diào)不減,每次修改后線(xiàn)段樹(shù)合并,判斷根節(jié)點(diǎn)的四種情況是否有合法的就行。
#include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long using namespace std; inline char _read() {static char buf[100000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline int read() {int x=0,f=1;char ch=_read();while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=_read();}while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=_read();}return x*f; } int n,m; int x,y; int s[800010][3][3]; int v[400010][3]; void pushup(int rt,int l,int r) {int mid=(l+r)>>1;for(int i=0;i<=1;i++){for(int j=0;j<=1;j++){ s[rt][i][j]=0;for(int k=0;k<=1;k++){for(int l=0;l<=1;l++){s[rt][i][j]|=s[rt<<1][i][k]&s[rt<<1|1][l][j]&(v[mid][k]<=v[mid+1][l]);}}}} } void build(int rt,int l,int r) {if(l==r){s[rt][0][0]=s[rt][1][1]=1;return ;}int mid=(l+r)>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);pushup(rt,l,r); } void change(int rt,int l,int r,int k) {if(l==r){s[rt][0][0]=s[rt][1][1]=1;return ;}int mid=(l+r)>>1;if(k<=mid){change(rt<<1,l,mid,k);}else{change(rt<<1|1,mid+1,r,k);}pushup(rt,l,r); } int main() {n=read();for(int i=1;i<=n;i++){v[i][0]=read();v[i][1]=read();}build(1,1,n);m=read();for(int i=1;i<=m;i++){x=read();y=read();swap(v[x][0],v[y][0]);swap(v[x][1],v[y][1]);change(1,1,n,x);change(1,1,n,y);if(s[1][1][1]|s[1][1][0]|s[1][0][0]|s[1][0][1]){printf("TAK\n");}else{printf("NIE\n");}}return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/Khada-Jhin/p/9681661.html
總結(jié)
以上是生活随笔為你收集整理的BZOJ3526[Poi2014]Card——线段树合并的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 前端开发学习笔记 - 1. Node.J
- 下一篇: 烧流量还是打矩阵,短视频不疯魔不成活?