[la P4487] Exclusive-OR

Time limit 3000 ms  OS Linux

You are not given n non-negative integers X0, X1, . . . , Xn−1 less than 220, but they do exist, and their values never change.

I’ll gradually provide you some facts about them, and ask you some questions.

There are two kinds of facts, plus one kind of question:

Format Meaning

I p v I tell you Xp = v

I p q v I tell you Xp XOR Xq = v

Q k p1 p2 . . . pk Please tell me the value of Xp1 XOR Xp2 XOR . . . XOR Xpk

Input

There will be at most 10 test cases. Each case begins with two integers n and Q (1 ≤ n ≤ 20, 000, 2 ≤ Q ≤ 40, 000). Each of the following lines

contains either a fact or a question, formatted as stated above.

The k parameter in the questions will be a positive integer not greater than 15, and the v parameter in the facts will be a non-negative integer less

than 220. The last case is followed by n = Q = 0, which should not be processed.

Output

For each test case, print the case number on its own line, then the answers, one on each one. If you can’t deduce the answer for a particular

question, from the facts I provide you before that question, print ‘I don’t know.’, without quotes. If the i-th fact (don’t count questions) cannot

be consistent with all the facts before that, print ‘The first i facts are conflicting.’, then keep silence for everything after that (including

facts and questions).

Print a blank line after the output of each test case.

Sample Input
2 6
I 0 1 3
Q 1 0
Q 2 1 0
I 0 2
Q 1 1
Q 1 0
3 3
I 0 1 6
I 0 2 2
Q 2 1 2
2 4
I 0 1 7
Q 2 0 1
I 0 1 8
Q 2 0 1
0 0

Sample Output
Case 1:
I don’t know.
3
1
2
Case 2:
4
Case 3:
7
The first 2 facts are conflicting.

很好的一道题目!大力推荐,只是如果认真做,有可能会续掉很长时间。

题目的意思是,给你一系列的操作,有3种形式:

1.I p v 告诉我们Xp=v

2.I p q v 告诉我们Xp^Xq=v

3.Q k p1 p2 ... pk 问我们 Xp1^Xp2^...^Xpk的值。

当然,如果在某个1或2操作时,我们得到的信息与我们已知信息冲突,输出在第几条信息(不包括询问)产生矛盾。

对于每个询问,如果并不能确定答案,输出I don't know.

好的,当我们读懂题目后,就可以思考了。

想一想,这和什么算法或数据结构有关联呢?

这一题我们采用并查集(加权)。

其实我原来想的已经很像正解了,但是由于没有想到“Q”操作,然后就GG了。

好的,我们来讲讲这题怎么用的并查集。

我们用fa[i]表示i的父亲,sum[i]表示从i到i所在的树的根节点,每个点的X值的xor值。

为了便于判断,我们刻意加上一个超级点——0。0的值已知,为0。刚开始的时候,所有节点的父亲都是自己,值未知(为了方便仍设为0)。

则对于1操作:

先判断是否矛盾。怎么样是矛盾的?仅当p的祖先是0时有可能,还要考虑权值。

首先,我们会(或是必要的)进行路径压缩,此时,sum[p]已经更新了,由于fa[p]=0,X[0]=0,所以x[p]=sum[p]。

也就是说,getfa(p)一遍(同时进行路径压缩并正确更新sum),判断v==sum[p]就好了。

如果原来不知道这个信息,则合并fa[p]和0。注意0永远要是一棵树的根节点。

这样的话,sum[getfa(p)]就是sum[p]^v了。

对于操作2,相当于一棵树中的判断或两颗树的合并。

判断的图:

下面p和q的连线可以看做是有向的,不管是上面方向,都应该有sum[p]^sum[q]==v,这就是判断。

合并操作:

应该很明显了吧,用的就是xor的性质,因为sum[q]=v^sum[p]^sum[x],所以sum[x]=sum[p]^sum[q]^v。

注意x不能为0,为0了就和y点swap一下,不可能同时x==0且y==0。

稍微要动一下脑袋的就是“Q”操作。

我们知道,这些给出的点可能是在不同的树里面,但这并不代表不能算出来。

当我们路径压缩后会是这种情况:

这些点的父节点就是根节点,所以不进行区分,就直接说父节点好了。有些点的父节点可能是自己,也可能是其他,还有可能是0。

我们可以把询问的答案变成:

sum[p1]^sum[fa[p1]]^sum[p2]^sum[fa[p2]]^sum[p3]^sum[fa[p3]]^...

那么,由于每一棵树的根节点(除0外)的sum都是0,也就是不知道其权值。

但是,根据xor的性质,一个数xor偶数次就消去了。所以我们判断一下所有非0的fa[px]出现的次数到底是奇数次还是偶数次。

当且仅当出现偶数次,是有解的,解就是sum[p1]^sum[p2]^sum[p3]^...,否则就是I don't know.了。

再注意一下,正确的getfa应该长这样:

 inline int get(int x) {
     if (fa[x]==x) {
         return x;
     }
     int p=fa[x];
     fa[x]=get(fa[x]);
     sum[x]^=sum[p];
     return fa[x];
 }

还有一点,就是把告诉你单点值那个操作归到第2种也是可以的,注意一下无论何时,根为0就行了。

code 1:

 #include <cstdio>
 #include <cstring>
 #include <algorithm>
 #include <iostream>
 ;
 int n,q,len,fa[N],ew[N];
 ],ero,fac,ans,tag;
 ]; bool cnt[N];
 void read() {
     gets(s),len=strlen(s);
     num[]=;
     ; i<len; ++i) {
         ') {
             num[++num[]]=;
         }
         else {
             num[num[]]=num[num[]]*+s[i]-';
         }
     }
     ]=='I') {
         ++fac;
         ]==) {
             ++num[];
         }
         else {
             ++num[]; ++num[];
         }
     }
     else {
         ; i<=num[]; ++i) {
             ++num[i];
         }
     }
 }
 inline int get(int x) {
     if (fa[x]==x) {
         return x;
     }
     int p=fa[x];
     fa[x]=get(fa[x]);
     ew[x]^=ew[p];
     return fa[x];
 }
 int main() {
     ;
     while (scanf("%d%d",&n,&q)!=EOF,n||q) {
         printf(,fac=;
         ; i<=n+; i++) {
             fa[i]=i; ew[i]=;
         }
         fa[]=; ew[]=;
         getchar();
         ; cq<=q; ++cq) {
             read();
             if (ero) {
                 continue;
             }
             ]=='I') {
                 ]==) {
                     x=]);
                     &&ew[num[]]!=num[]) {
                         ero=;
                         printf("The first %d facts are conflicting.\n",fac);
                     }
                     else {
                         x=]);
                         fa[x]=; ew[x]=ew[num[]]^num[];
                     }
                     continue;
                 }
                 x=]),y=]);
                 if (x==y) {
                     ]]^ew[num[]])!=num[]) {
                         ero=;
                         printf("The first %d facts are conflicting.\n",fac);
                     }
                     continue;
                 }
                 ) {
                     std::swap(num[],num[]);
                     std::swap(x,y);
                 }
                 fa[y]=x; ew[y]=ew[num[]]^ew[num[]]^num[];
             }
             else
             ]=='Q') {
                 ans=; tag=;
                 ; i<=num[]; ++i) {
                     x=get(num[i]);
                     ans^=ew[num[i]];
                     num[i]=x;
                     cnt[x]^=;
                 }
                 ; i<=num[]; ++i) {
                     ) {
                         tag=;
                         break;
                     }
                 }
                 ; i<=num[]; ++i) {
                     cnt[num[i]]=;
                 }
                 if (tag) {
                     printf("I don't know.\n");
                 }
                 else {
                     printf("%d\n",ans);
                 }
             }
         }
         putchar('\n');
     }
     ;
 }

code 2:(稍微排布好看了一点qwq)

 #include <cstdio>
 #include <cstring>
 #include <algorithm>
 #include <iostream>
 ;
 int n,q,len,fa[N],sum[N];
 ],ero,fac;
 ]; bool cnt[N];
 void init() {
     gets(s); len=strlen(s); num[]=;
     ; i<len; ++i) {
         ') {
             num[++num[]]=;
         }
         else {
             num[num[]]=num[num[]]*+s[i]-';
         }
     }
     ]=='I') {
         ++fac;
         ]==) {
             num[]=num[]; num[]=++num[]; num[]=;
         }
         else {
             ++num[]; ++num[];
         }
     }else
     ]=='Q') {
         ; i<=num[]; ++i) {
             ++num[i];
         }
     }
 }
 inline int get(int x) {
     if (fa[x]==x) {
         return x;
     }
     int p=fa[x];
     fa[x]=get(fa[x]);
     sum[x]^=sum[p];
     return fa[x];
 }
 int main() {
     ;
     while (scanf("%d%d",&n,&q),n||q) {
         printf("Case %d:\n",++cas);
         fac=; ero=;
         ; i<=n; ++i) {
             fa[i]=i; sum[i]=;
         }
         getchar();
         for (; q; --q) {
             init();
             if (ero) continue;
             ]=='I') {
                 x=]); y=]);
                 ]]^sum[num[]])!=num[]) {
                     ero=;
                     printf("The first %d facts are conflicting.\n",fac);
                     continue;
                 }
                 ) {
                     std::swap(x,y);
                     std::swap(num[],num[]);
                 }
                 fa[y]=x; sum[y]=sum[num[]]^sum[num[]]^num[];
             }else
             ]=='Q') {
                 ans=; tag=;
                 ; i<=num[]; ++i) {
                     x=get(num[i]);
                     ans^=sum[num[i]];
                     num[i]=x;
                     cnt[x]^=;
                 }
                 ; i<=num[]; ++i) {
                     if (cnt[num[i]]&&num[i]) {
                         tag=;
                         break;
                     }
                 }
                 ; i<=num[]; ++i) {
                     cnt[num[i]]=;
                 }
                 if (tag) {
                     printf("I don't know.\n");
                 }
                 else {
                     printf("%d\n",ans);
                 }
             }
         }
         putchar('\n');
     }
     ;
 }

[la P4487] Exclusive-OR的更多相关文章

  1. leggere la nostra recensione del primo e del secondo

    La terra di mezzo in trail running sembra essere distorto leggermente massima di recente, e gli aggi ...

  2. Le lié à la légèreté semblait être et donc plus simple

    Il est toutefois vraiment à partir www.runmasterfr.com/free-40-flyknit-2015-hommes-c-1_58_59.html de ...

  3. ORA-01102: cannot mount database in EXCLUSIVE mode

    安装完ORACEL 10g数据库后,启动数据库时遇到ORA-01102: cannot mount database in EXCLUSIVE mode [oracle@DB-Server ~]$ s ...

  4. Activiti之 Exclusive Gateway

    一.Exclusive Gateway Exclusive Gateway(也称为XOR网关或更多技术基于数据的排他网关)经常用做决定流程的流转方向.当流程到达该网关的时候,所有的流出序列流到按照已定 ...

  5. Mac Pro 使用 ll、la、l等ls的别名命令

    在 Linux 下习惯使用 ll.la.l 等ls别名的童鞋到 mac os 可就郁闷了~~ 其实只要在用户目录下建立一个脚本“.bash_profile”, vim .bash_profile 并输 ...

  6. Linux中的动态库和静态库(.a/.la/.so/.o)

    Linux中的动态库和静态库(.a/.la/.so/.o) Linux中的动态库和静态库(.a/.la/.so/.o) C/C++程序编译的过程 .o文件(目标文件) 创建atoi.o 使用atoi. ...

  7. Mac OS使用ll、la、l等ls的别名命令

    在linux下习惯使用ll.la.l等ls别名的童鞋到mac os可就郁闷了-- 其实只要在用户目录下建立一个脚本“.bash_profile”,并输入以下内容即可: alias ll='ls -al ...

  8. 启动weblogic的错误:Could not obtain an exclusive lock to the embedded LDAP data files directory

    http://hi.baidu.com/kaisep/item/0e4bf6ee5da001d1ea34c986 源地址 启动weblogic的错误:Could not obtain an exclu ...

  9. .Uva&LA部分题目代码

    1.LA 5694 Adding New Machine 关键词:数据结构,线段树,扫描线(FIFO) #include <algorithm> #include <cstdio&g ...

随机推荐

  1. 帮助Bsny(乱搞做法)

    帮助Bsny 题目描述 Bsny的书架乱成一团了,帮他一下吧! 他的书架上一共有n本书,我们定义混乱值是连续相同高度书本的段数.例如,如果书的高度是30,30,31,31,32,那么混乱值为3:30, ...

  2. Linux中LAMP构架的实现

    LAMP:Linux+Apache+Mysql+Perl/PHP/Python一组常用来搭建动态网站或者服务器的开源软件,本身都是各自独立的程序,但是因为常被放在一起使用,拥有了越来越高的兼容度共同组 ...

  3. 小白のjava实现wc.exe功能

    GitHub地址 项目完成情况 基本功能列表(已实现) wc.exe -c file.c     //返回文件 file.c 的字符数 wc.exe -w file.c    //返回文件 file. ...

  4. MySQL删除foreign key_ERROR 1025 (HY000): Error on rename of './test_20180206/cc' to './test_20180206/#sql2-9ac-e' (errno: 152)

    问题背景描述: 首先,创建了一个主表,具有以下数据结构: mysql> describe aa; +-------+----------+------+-----+---------+----- ...

  5. centos6/7破解root密码的操作

    Centos 6 1.开机按“Esc”键 2.按e键进入编辑模式后,选择Kernel /vmlinuz-2.6.92......项 3.进入该编辑模式后,在quiet后面输入simple或者数字1后, ...

  6. Unity Ragdoll 实现死亡效果 心得+坑点总结

    效果展示 正如其名,Ragdoll可以让人物模型实现像布娃娃一样物理效果 创建Ragdoll 在场景中新建 3D Object → Ragdoll... 接下来是一个初见复杂的绑定界面,这里我做了简单 ...

  7. Unity 新手入门 如何理解协程 IEnumerator yield

    Unity 新手入门 如何理解协程 IEnumerator 本文包含两个部分,前半部分是通俗解释一下Unity中的协程,后半部分讲讲C#的IEnumerator迭代器 协程是什么,能干什么? 为了能通 ...

  8. Let’s Encrypt 通配符证书申请配置

    首先你可以查看下官方提供的支持申请通配符证书的客户端列表:https://letsencrypt.org/docs/client-options/. 这些客户端支持最新的ACME v2接口,而这个接口 ...

  9. GitHub Toturial

    GitHub Toturial Git Summary 1. 设置姓名和email git config --global user.name "YuboFeng" git con ...

  10. Mysql索引使用解析

    摘自:http://blog.chinaunix.net/uid-25063573-id-3032578.html Mysql索引使用解析 1.索引作用 在索引列上,除了上面提到的有序查找之外,数据库 ...