博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

BZOJ:4333: JSOI2012 智者的考验

4333: JSOI2012 智者的考验

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 68  Solved: 18
[Submit][Status][Discuss]

Description

公元1371年,太祖下令在北极阁上大建庙宇,短短几年,鸡笼山上便建成了帝王庙、关公庙、真武庙、功臣庙、蒋王庙、都城隍庙、卞壶庙、忠烈庙、刘越王庙、曹武惠王庙共十座庙宇,统称为“十庙”。 
后来,为了方便人们来鸡笼山进香礼佛,太祖下令疏通了鸡笼山下已淤塞多年的潮沟。于是,便有了“进香河”。 
然而并不是所有人都可以来鸡笼山的,太祖在进香河上修建了一座石桥,中间悬挂了一块高Rx宽Ry的机关格图(如下图所示)。所有格子都是活动可翻转的,一面是白色,一面是黑色,这里我们用0表示白色,用1表示黑色。初始情况下,所有格子都是白色面朝前的。有Rx+Ry个机关按钮,对应Rx行和Ry列。一个按钮一旦触发,就会引发对应的一行或一列的格子同时翻转。 
 
同时,善于识天象的谋臣刘基给出了一种黑白状态,称之为“厄运星”。每一位过往前去鸡笼山的人都需要触发且只触发一个按钮,触发后,如果来访者呈“厄运星”形状,则不允许通过。 
每一天要来鸡笼山的人数N是事先就知道的,同时天朝神威浩荡,每一位来者一开始总是有很大概率触发编号为1的按钮,我们不妨用数列A1,A2,…,AN来表示,问题保证了初始时候的A数列全为1。同时在整个问题中,Ai满足1<=Ai<=Rx+Ry。太祖很关心那些不允许去鸡笼山的人数。于是他时不时就会询问关于“某一段时间内会有多少人不能通过“厄运星”的考验”。然而那些前来鸡笼山的文人墨客并不愿意如此单一的操作。来访者有可能会突然决定修改自己的触发按钮。更麻烦的情况,结伴而来的连续若干人会突然决定修改触发按钮并且都去触发同一个按钮。 
现在这麻烦的问题交给了你。 
 
后记: 
等到了乾隆时期,一位人称纪昀的才子来访此地,告诉了人们一套方法,从此再也没有人会不被允许通过了。久而久之,鸡笼山烟火依旧,然这机关格图的故事便渐渐失传了。直到今天才再一次被世人所了解。 
 

 

Input

输入文件第一行有2个数字Rx和Ry表示机关格图的高和宽(如图所示)。之后Rx行每一行Ry个数字,描述了“厄运星”形状,每一个数字都满足非0即1. 
之后一行有两个数字,分别为N和M,表示人数和询问修改的次数。 
之后M行,对应M次询问或修改。每一行先有一个数字t: 
若t为0:之后有2个数字d和x,表明将Ad修改为x。 
若t为1:之后有2个数字l和r,表明询问第l个人到第r个人中有多少人触发按钮后会出现“厄运星”形状,从而无法通过。
若t为2:之后有3个数字l,r和x,表面将Al,Al+1,…,Ar-1,Ar都修改为x。 
 

 

Output

对于每一次询问(即t为1的情况),输出单独一行,一个整数描述了在区间[l,r]中满足要求的人数。 
 

 

Sample Input

2 3
0 0 1
1 1 0
7 4
1 1 7
0 2 3
0 3 4
1 1 7

Sample Output

0
3
 
(有时候还是觉得复制一下题面挺好的
问题显然可以转化成带修地查询区间内前缀异或和为给定数的数量。
嗯?好像有64种状态?
不对不对,5个按钮应该是2^5=32种状态?
哦,把所有按钮都取反跟原来是一样,那就是2^4=16种状态。
那就可做了!
区间修改为某个数的影响最多只有1次(两两抵消)。
线段树上打打标记就可以了(我怎么还写了一早上啊)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MN 1000001
using namespace std;

int read_p,read_ca;
inline int read(){
    read_p=0;read_ca=getchar();
    while(read_ca<'0'||read_ca>'9') read_ca=getchar();
    while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
    return read_p;
}
struct na{int c[16],sum,l,r,y,a,Q,V;}t[MN<<1];
int n,m,q,rx,ry,o[10],s[16],to[16][10],num=0,bo,ro=0,x,N[64];
void build(int &p,int l,int r){
    if (p==0) p=++num,t[p].l=t[p].r=t[p].sum=t[p].y=0,t[p].a=-1;
    t[p].c[N[0]]=((r-l)>>1)+(!(l&1)||!(r&1));
    t[p].c[N[o[0]]]=((r-l)>>1)+((l&1)||(r&1));t[p].sum=((((r-l)>>1)+((l&1)||(r&1)))&1)*o[0];
    if (l==r) return;
    int mid=l+r>>1;
    build(t[p].l,l,mid);build(t[p].r,mid+1,r);
}
void pd(int p,int l,int r){
    if (t[p].a!=-1){
        if (t[p].l) t[t[p].l].a=t[p].a,t[t[p].l].V=t[p].V,t[t[p].l].Q=t[p].Q,t[t[p].l].y=0;
        if (t[p].r) t[t[p].r].a=t[p].a,t[t[p].r].V=t[p].V,t[t[p].r].Q=t[p].Q,t[t[p].r].y=0;
        memset(t[p].c,0,sizeof(t[p].c));
        t[p].c[N[t[p].V]]=((r-l)>>1)+(!(l-t[p].Q&1)||!(r-t[p].Q&1));
        t[p].c[N[t[p].a^t[p].V]]=((r-l)>>1)+((l-t[p].Q&1)||(r-t[p].Q&1));t[p].sum=((((r-l)>>1)+((l-t[p].Q&1)||(r-t[p].Q&1)))&1)*t[p].a^((r-l+1&1)*t[p].V);
        t[p].a=-1;
    }
}
void up(int p,int l,int r){
    int mid=l+r>>1;
    pd(t[p].l,l,mid);pd(t[p].r,mid+1,r);
    t[p].sum=t[t[p].l].sum^t[t[p].r].sum^(((mid-l+1)&1)*t[t[p].l].y)^(((r-mid)&1)*t[t[p].r].y);
    for (int i=0;i<16;i++) t[p].c[i]=t[t[p].l].c[N[s[i]^t[t[p].l].y]]+t[t[p].r].c[N[s[i]^t[t[p].r].y]];
}
void cg(int p,int l,int r,int po,int v){
    if (po<=l) t[p].y^=v;else{
        pd(p,l,r);
        int mid=l+r>>1;
        cg(t[p].r,mid+1,r,po,v);
        if (mid>=po) cg(t[p].l,l,mid,po,v);
        up(p,l,r);
    }
}
int ask(int p,int l,int r,int po){
    if (t[p].a!=-1) return (t[p].a*(po-t[p].Q&1))^t[p].V^t[p].y;
    if (l==r) return t[p].sum^t[p].y;
    int mid=l+r>>1;
    if (po<=mid) return ask(t[p].l,l,mid,po)^t[p].y;else return ask(t[p].r,mid+1,r,po)^t[p].y;
}
int que(int p,int l,int r,int L,int R,int v){
    pd(p,l,r);
    v^=t[p].y;
    if (L==l&&R==r) return t[p].c[N[v]];
    int mid=l+r>>1;
    if (R<=mid) return que(t[p].l,l,mid,L,R,v);else
    if (L>mid) return que(t[p].r,mid+1,r,L,R,v);else
    return que(t[p].l,l,mid,L,mid,v)+que(t[p].r,mid+1,r,mid+1,R,v);
}
void ca(int p,int l,int r,int L,int R,int v,int V,int Q){
    if (L==l&&R==r){
        t[p].a=v;t[p].V=V;t[p].y=0;t[p].Q=Q;
        t[p].c[N[V]]=((r-l)>>1)+(!(l-Q&1)||!(r-Q&1));
        t[p].c[N[v^V]]=((r-l)>>1)+((l-Q&1)||(r-Q&1));t[p].sum=(((((r-l)>>1)+((l-Q&1)||(r-Q&1)))&1)*v)^((r-l+1&1)*V);
    }else{
        pd(p,l,r);V^=t[p].y;
        int mid=l+r>>1;
        if (R<=mid) ca(t[p].l,l,mid,L,R,v,V,Q);else
        if (L>mid) ca(t[p].r,mid+1,r,L,R,v,V,Q);else
        ca(t[p].l,l,mid,L,mid,v,V,Q),ca(t[p].r,mid+1,r,mid+1,R,v,V,Q);
        up(p,l,r);
    }
}
int main(){
    register int i,j;
    rx=read();ry=read();n=0;
    for (i=0;i<rx;i++)
    for (j=0;j<ry;j++) o[i]^=1<<(i*ry+j),o[j+rx]^=1<<(i*ry+j),q^=read()<<(i*ry+j);
    n=read();m=read();
    s[bo=num=0]=0;
    for(;bo<=num;){
        for (i=0;i<rx+ry;i++){
            for (j=0;j<=num;j++)
            if (s[j]==(s[bo]^o[i])) break;
            if (j>num) s[++num]=s[bo]^o[i];
            to[bo][i]=j;
        }
        bo++;
    }
    for (i=0;i<64;i++) N[i]=-1;
    for (i=0;i<=num;i++) N[s[i]]=i;
    num=0;
    build(ro,1,n);
    while (m--){
        bo=read();
        if (bo==0) bo=read(),cg(ro,1,n,bo,o[read()-1]^ask(ro,1,n,bo)^(bo==1?0:ask(ro,1,n,bo-1)));else
        if (bo==1) if (bo=read(),x=read(),N[q]==-1) puts("0");else printf("%d\n",que(ro,1,n,bo,x,q));else
        if (rx=read(),ry=read(),x=o[read()-1],cg(ro,1,n,ry+1,ask(ro,1,n,ry)^(((ry-rx+1)&1)*x)),ca(ro,1,n,rx,ry,x,0,rx-1),rx-1) cg(ro,1,n,rx,ask(ro,1,n,rx-1));
    }
}
View Code

 

 
 
posted @ 2017-04-14 12:48  swm_sxt  阅读(408)  评论(0编辑  收藏  举报