[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. final关键字的几种用法

    在java的关键字中,static和final是两个我们必须掌握的关键字.不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构.下面我们来了解一下final ...

  2. QQ/微信中被禁止访问的网页怎么打开

    为什么关心这种技术?因为我经常听到身边搞微商.搞微信项目的朋友都在叫苦连天,由于微信域名屏蔽.微信域名被拦截.弄得他们尸横遍野,损失的连过年回家的路费都没了,曾经的叱咤风云一下变成了今日的倒亏损.腾讯 ...

  3. python,Day2,基础 2

    list和dict list是一种有序的集合,可以随时添加和删除其中的元素. 例如: >>>classmates = ['eason','grace','alice'] >&g ...

  4. Keepalived配置文件详解

    global_defs { router_id LVS_$prio #节点唯一标识,通常为hostname } local_address_group laddr_g1 { ${lvs_node} # ...

  5. 2018-2019-2 《网络对抗技术》Exp0 Kali安装 Week1 20165335

    一.资源下载以及工具安装 1.下载虚拟机工具VMware. 下载链接 :https://www.baidu.com/link?url=uuaBW5ETUl3GrhUKvPbbEc7QlQvGHfpD8 ...

  6. Oarcle之group by关键字与having关键字

    group by关键字    *group by :分组由 作用: 用于对于查询的数据进行分组并进行处理 例如:select deptno ,job from emp group by deptno, ...

  7. Liunx中三种网络模式配置及Xshell连接

    Liunx网络配置 NAT模式下的网络配置: 首先打开网络配置文件:vi   /etc/sysconfig/network-scripts/ifcfg-ens33 修改网卡信息,配置动态Ip过程中,只 ...

  8. react中对于context的理解

    一.context旧版的基本使用 1.context的理解 当不想在组件树中通过逐层传递props或state的方式来传递数据时,可使用context来实现跨层级的组件数据传递. 2.context的 ...

  9. C# WMI通过网络连接名称获取IP掩码网关

    /// <summary> /// 读取IP,掩码,网关地址 /// </summary> /// <param name="netConnectorName& ...

  10. jQuery实现input框输入值动态搜索

    我们在平时的前端开发中,经常会遇到添加数据,如果在添加之前要指定某个用户或对象进行关联,那在实现上要比普通的添加要繁琐一点.我本来的想法是给一个iframe,在 里面显示所有的数据并提供一个筛选的功能 ...