[BZOJ]3526: [Poi2014]Card
阿新 • • 發佈:2019-02-04
ont NPU uil spa 交換 date -- const sin
Submit: 409 Solved: 300
[Submit][Status][Discuss]
2 5
3 4
6 3
2 7
2
3 4
1 3
TAK
題解: 線段樹區間合並
只需要維護兩端 再選正面或反面時4種情況是否滿足情況 合並的話 考慮左兒子的右端點 右兒子的左端點的大小關系 然後合並
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set> #include <map> #define mp make_pair #define pb push_back #define pii pair<int,int> #define link(x) for(edge *j=h[x];j;j=j->next) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=3e5+10; const double eps=1e-8; #define ll long long const int inf=1e9; using namespace std; struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e; void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;} ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar(); return x*f; } bool tag[MAXN<<2][4]; int a[MAXN][2]; bool Max(bool t1,bool t2){ if(t1)return true; if(t2)return true; return false; } void up(int rt,int l,int r){ int mid=(l+r)>>1; inc(i,0,3)tag[rt][i]=0; inc(i,0,3)inc(j,0,3){ if(a[2*mid][i&1]<=a[2*mid+1][(j>>1)&1]){ tag[rt][(i&2)+(j&1)]=Max(tag[rt][(i&2)+(j&1)],(tag[rt<<1][i]&tag[rt<<1|1][j])); } } } void built(int rt,int l,int r){ if(l==r){ inc(i,0,3){ if(a[2*l-1][(i>>1)&1]<=a[2*l][i&1])tag[rt][i]=1; } return ; } int mid=(l+r)>>1; built(rt<<1,l,mid); built(rt<<1|1,mid+1,r); up(rt,l,r); } void update(int rt,int l,int r,int t){ if(l==r){ inc(i,0,3){ if(a[2*l-1][(i>>1)&1]<=a[2*l][i&1])tag[rt][i]=1; else tag[rt][i]=0; } return ; } int mid=(l+r)>>1; if(t<=mid)update(rt<<1,l,mid,t); else update(rt<<1|1,mid+1,r,t); up(rt,l,r); } int main(){ int n=read(); inc(i,1,n){ a[i][0]=read(),a[i][1]=read(); if(a[i][0]>a[i][1])swap(a[i][0],a[i][1]); } if(n&1)n++,a[n][0]=a[n][1]=inf; n/=2; built(1,1,n); int m=read(); while(m--){ int x=read();int y=read(); swap(a[x][0],a[y][0]); swap(a[x][1],a[y][1]); update(1,1,n,(x-1)/2+1);update(1,1,n,(y-1)/2+1); bool flag=0; inc(i,0,3)if(tag[1][i])flag=1; if(flag)puts("TAK"); else puts("NIE"); } return 0; }
3526: [Poi2014]Card
Time Limit: 25 Sec Memory Limit: 64 MBSubmit: 409 Solved: 300
[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
42 5
3 4
6 3
2 7
2
3 4
1 3
Sample Output
NIETAK
[BZOJ]3526: [Poi2014]Card