BZOJ 3526: [Poi2014]Card
3526: [Poi2014]Card
Time Limit: 25 Sec Memory Limit: 64 MBSubmit: 267 Solved: 191
[Submit][Status][Discuss]
Description
有n张卡片在桌上一字排开,每张卡片上有两个数,第i张卡片上,正面的数为a[i],反面的数为b[i]。现在,有m个熊孩子来破坏你的卡片了!
第i个熊孩子会交换c[i]和d[i]两个位置上的卡片。
每个熊孩子捣乱后,你都需要判断,通过任意翻转卡片(把正面变为反面或把反面变成正面,但不能改变卡片的位置),能否让卡片正面上的数从左到右单调不降。
Input
第一行一个n。
接下来n行,每行两个数a[i],b[i]。
接下来一行一个m。
接下来m行,每行两个数c[i],d[i]。
Output
m行,每行对应一个答案。如果能成功,输出TAK,否则输出NIE。
Sample Input
4
2 5
3 4
6 3
2 7
2
3 4
1 3
2 5
3 4
6 3
2 7
2
3 4
1 3
Sample Output
NIE
TAK
TAK
HINT
【样例解释】
交换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.
Source
好有趣的一道题,老早就写过,现在又重新写一遍,强行缩代码,2333.
就是用线段树,维护每个区间,如果选取区间左端较小值,右端能以什么结尾;如果选取区间左端较大值,右端能以什么结尾。
1 #include<cstdio> 2 #define mxn 200005 3 #define siz 800005 4 #define mxm 1000005 5 #define swap(a,b) a^=b^=a^=b 6 int n,m,a[mxn],b[mxn],c,d,A[siz],B[siz]; 7 void update(int t,int l,int r,int d,int ls,int rs){ 8 A[t]=B[t]=0; 9 if((A[ls]==1&&a[d]<=b[d+1])||(A[ls]==2&&b[d]<=b[d+1]))A[t]=B[rs]; 10 if((A[ls]==1&&a[d]<=a[d+1])||(A[ls]==2&&b[d]<=a[d+1]))A[t]=A[rs]; 11 if((B[ls]==1&&a[d]<=b[d+1])||(B[ls]==2&&b[d]<=b[d+1]))B[t]=B[rs]; 12 if((B[ls]==1&&a[d]<=a[d+1])||(B[ls]==2&&b[d]<=a[d+1]))B[t]=A[rs]; 13 } 14 void build(int t,int l,int r){ 15 if(l==r){A[t]=1;B[t]=2;return;} 16 int d=(l+r)>>1,ls=t<<1,rs=t<<1|1; 17 build(ls,l,d),build(rs,d+1,r); 18 update(t,l,r,d,ls,rs); 19 } 20 void rebuild(int t,int l,int r,int p){ 21 if(l==r){A[t]=1;B[t]=2;return;} 22 int d=(l+r)>>1,ls=t<<1,rs=t<<1|1; 23 if(p<=d)rebuild(ls,l,d,p);else rebuild(rs,d+1,r,p); 24 update(t,l,r,d,ls,rs); 25 } 26 main(){ 27 scanf("%d",&n); 28 for(int i=1;i<=n;++i)scanf("%d%d",a+i,b+i); 29 for(int i=1;i<=n;++i)if(a[i]>b[i])swap(a[i],b[i]); 30 build(1,1,n); 31 scanf("%d",&m); 32 for(int i=1;i<=m;++i)scanf("%d%d",&c,&d),puts((swap(a[c],a[d]),swap(b[c],b[d]),rebuild(1,1,n,c),rebuild(1,1,n,d),A[1])?"TAK":"NIE"); 33 }
原来的代码看起来好冗长的样子……
1 #include <cmath> 2 #include <cstdio> 3 #include <string> 4 #include <cstring> 5 #include <cstdlib> 6 #include <iostream> 7 #include <algorithm> 8 9 using namespace std; 10 11 const int N = 200005; 12 const int M = 1000005; 13 14 int n, m; 15 16 struct card 17 { 18 int a, b; 19 20 card(void) {}; 21 card(int _a, int _b) 22 { 23 a = min(_a, _b); 24 b = max(_a, _b); 25 } 26 }c[N]; 27 28 struct node 29 { 30 int lt, rt; 31 int valA, valB; 32 }tree[N << 2]; 33 34 void buildTree(int p, int l, int r) 35 { 36 node &t = tree[p]; 37 38 t.lt = l, t.rt = r; 39 40 if (t.lt == t.rt) 41 { 42 t.valA = 1; 43 t.valB = 2; 44 45 return; 46 } 47 48 int mid = (t.lt + t.rt) >> 1; 49 50 buildTree(p << 1, t.lt, mid); 51 buildTree(p << 1 | 1, mid + 1, t.rt); 52 53 t.valA = t.valB = 0; 54 55 switch (tree[p << 1].valA) 56 { 57 case 1: 58 if (c[mid].a <= c[mid + 1].b) 59 t.valA = tree[p << 1 | 1].valB; 60 if (c[mid].a <= c[mid + 1].a) 61 t.valA = tree[p << 1 | 1].valA; 62 break; 63 case 2: 64 if (c[mid].b <= c[mid + 1].b) 65 t.valA = tree[p << 1 | 1].valB; 66 if (c[mid].b <= c[mid + 1].a) 67 t.valA = tree[p << 1 | 1].valA; 68 break; 69 } 70 71 switch (tree[p << 1].valB) 72 { 73 case 1: 74 if (c[mid].a <= c[mid + 1].b) 75 t.valB = tree[p << 1 | 1].valB; 76 if (c[mid].a <= c[mid + 1].a) 77 t.valB = tree[p << 1 | 1].valA; 78 break; 79 case 2: 80 if (c[mid].b <= c[mid + 1].b) 81 t.valB = tree[p << 1 | 1].valB; 82 if (c[mid].b <= c[mid + 1].a) 83 t.valB = tree[p << 1 | 1].valA; 84 break; 85 } 86 } 87 88 void change(int p, int pos) 89 { 90 node &t = tree[p]; 91 92 if (t.lt == t.rt) 93 { 94 t.valA = 1; 95 t.valB = 2; 96 97 return; 98 } 99 100 int mid = (t.lt + t.rt) >> 1; 101 102 if (pos <= mid) 103 change(p << 1, pos); 104 else 105 change(p << 1 | 1, pos); 106 107 t.valA = t.valB = 0; 108 109 switch (tree[p << 1].valA) 110 { 111 case 1: 112 if (c[mid].a <= c[mid + 1].b) 113 t.valA = tree[p << 1 | 1].valB; 114 if (c[mid].a <= c[mid + 1].a) 115 t.valA = tree[p << 1 | 1].valA; 116 break; 117 case 2: 118 if (c[mid].b <= c[mid + 1].b) 119 t.valA = tree[p << 1 | 1].valB; 120 if (c[mid].b <= c[mid + 1].a) 121 t.valA = tree[p << 1 | 1].valA; 122 break; 123 } 124 125 switch (tree[p << 1].valB) 126 { 127 case 1: 128 if (c[mid].a <= c[mid + 1].b) 129 t.valB = tree[p << 1 | 1].valB; 130 if (c[mid].a <= c[mid + 1].a) 131 t.valB = tree[p << 1 | 1].valA; 132 break; 133 case 2: 134 if (c[mid].b <= c[mid + 1].b) 135 t.valB = tree[p << 1 | 1].valB; 136 if (c[mid].b <= c[mid + 1].a) 137 t.valB = tree[p << 1 | 1].valA; 138 break; 139 } 140 } 141 142 signed main(void) 143 { 144 scanf("%d", &n); 145 146 for (int i = 1, a, b; i <= n; ++i) 147 scanf("%d%d", &a, &b), c[i] = card(a, b); 148 149 buildTree(1, 1, n); 150 151 scanf("%d", &m); 152 153 for (int i = 1, a, b; i <= m; ++i) 154 { 155 scanf("%d%d", &a, &b); 156 157 swap(c[a], c[b]); 158 159 change(1, a); 160 change(1, b); 161 162 if (tree[1].valA) 163 puts("TAK"); 164 else 165 puts("NIE"); 166 } 167 }
@Author: YouSiki