POI2014Card
来源:互联网 发布:多头螺纹怎样用g92编程 编辑:程序博客网 时间:2024/05/20 03:44
这道题的话,想法感觉也是很奇怪的…
首先一个想法是如果有了第一个值,那么就可以贪心地去选取数字了,每次都选能选的最小的,这样肯定最优.
那么我们就去确定这个数,即可以讨论而得出一段区间右端点最小是什么.
我们可以看出,一段区间的左端点,要么是左边的第一个数,要么是左边的第二个数,然后对于一段没有被修改过的区间,它们定下来左端点后,右端点的最小值是固定的.
然后用线段树来优化它,每次进行单点更新,区间查询,就行了.
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define M 200005using namespace std;void Rd(int &res){ res=0;char p; while(p=getchar(),p<'0'); do{ res=(res<<1)+(res<<3)+(p^48); }while(p=getchar(),p>='0');}int n,m;int a[2][M];struct SegTree{ int Tree[2][M<<2]; void up(int L,int R,int p){ int mid=(L+R)>>1; if(Tree[0][p<<1]!=-1){ if(Tree[0][p<<1]<=a[0][mid+1])Tree[0][p]=Tree[0][p<<1|1]; else if(Tree[0][p<<1]<=a[1][mid+1])Tree[0][p]=Tree[1][p<<1|1]; else Tree[0][p]=-1; }else Tree[0][p]=-1; if(Tree[1][p<<1]!=-1){ if(Tree[1][p<<1]<=a[0][mid+1])Tree[1][p]=Tree[0][p<<1|1]; else if(Tree[1][p<<1]<=a[1][mid+1])Tree[1][p]=Tree[1][p<<1|1]; else Tree[1][p]=-1; }else Tree[1][p]=-1; } void build(int L,int R,int p){ if(L==R){ Tree[0][p]=a[0][L]; Tree[1][p]=a[1][L]; return; } int mid=(L+R)>>1; build(L,mid,p<<1); build(mid+1,R,p<<1|1); up(L,R,p); } void update(int L,int R,int p,int x){ if(L==R){ Tree[0][p]=a[0][x]; Tree[1][p]=a[1][x]; return; } int mid=(L+R)>>1; if(mid>=x)update(L,mid,p<<1,x); else update(mid+1,R,p<<1|1,x); up(L,R,p); }}T;int main(){ Rd(n); for(int i=1;i<=n;i++){ Rd(a[0][i]),Rd(a[1][i]); if(a[0][i]>a[1][i])swap(a[0][i],a[1][i]); } T.build(1,n,1); Rd(m); for(int i=1;i<=m;i++){ int x,y;Rd(x),Rd(y); swap(a[1][x],a[1][y]); swap(a[0][x],a[0][y]); T.update(1,n,1,x),T.update(1,n,1,y); if(T.Tree[0][1]!=-1||T.Tree[1][1]!=-1)puts("TAK"); else puts("NIE"); } return 0;}
0 0