zoukankan      html  css  js  c++  java
  • [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 MB
    Submit: 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

    Sample Output

    NIE
    TAK
  • 相关阅读:
    转载集合
    TYVJ P1053 字符串的展开 Label:字符 水
    划分数系列问题
    关于inf的问题
    TYVJ P1031 热浪 Label:dijkstra 最短路
    TYVJ P1032 零用钱 Label:贪心
    如何简单形象又有趣地讲解神经网络是什么?知乎
    CString
    利用afxDump来调试自己的程序
    mfc 调试 弹消息
  • 原文地址:https://www.cnblogs.com/wang9897/p/10351232.html
Copyright © 2011-2022 走看看