[BZOJ]3526: [Poi2014]Card
题解: 线段树区间合并
只需要维护两端 再选正面或反面时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
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

浙公网安备 33010602011771号