BZOJ3526[Poi2014]Card——线段树合并
生活随笔
收集整理的這篇文章主要介紹了
BZOJ3526[Poi2014]Card——线段树合并
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述
有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 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),翻轉第3張卡片,卡片的正面為2,3,5,6,可以成功。
【數據范圍】
n≤200000,m≤1000000,0≤a[i],b[i]≤10000000,1≤c[i],d[i]≤n.
?
線段樹合并好題。線段樹每個節點維護s[x][0/1][0/1],表示x節點對應區間左/右端點選正/背面區間能否單調不減,每次修改后線段樹合并,判斷根節點的四種情況是否有合法的就行。
#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; }轉載于:https://www.cnblogs.com/Khada-Jhin/p/9681661.html
總結
以上是生活随笔為你收集整理的BZOJ3526[Poi2014]Card——线段树合并的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端开发学习笔记 - 1. Node.J
- 下一篇: 烧流量还是打矩阵,短视频不疯魔不成活?