鱼C论坛

 找回密码
 立即注册
查看: 1625|回复: 8

[已解决]CSP-J 2020表达式 题目求助,代码看不出问题,求高人指导(本人自己想出来了)

[复制链接]
发表于 2023-4-2 17:44:11 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 zhangjinxuan 于 2023-7-10 20:43 编辑

题目链接:https://www.luogu.com.cn/problem/P7073
我的代码:
  1. #include <bits/stdc++.h>
  2. using namespace std;

  3. struct Node {
  4.         bool type; // 0 -> operator, 1 -> value
  5.         char c; // if type == 0, it means operator (&, |)
  6.         bool noted; // not -> !
  7.         bool ok; // If this change, result can change
  8.         int id; // number id
  9.         int l, r; //left, right sons
  10.         int value; //eval_value
  11. } a[500001];

  12. int nodtot, nums[1000001], numtot;
  13. int stak[1000001], top, root;
  14. int n, na[1000001], rootvalue, q, x;

  15. void get_ans(int r) {
  16.         if (a[r].type == 1) {
  17.                 a[r].value = na[a[r].id];
  18.                 if (a[r].noted) a[r].value = !a[r].value;
  19.                 return;
  20.         }
  21.         get_ans(a[r].l);
  22.         get_ans(a[r].r);
  23.         if (a[r].c == '&') {
  24.                 a[r].value = a[a[r].l].value & a[a[r].r].value;
  25.                 if (a[r].noted) a[r].value = !a[r].value;
  26.         } else {
  27.                 a[r].value = a[a[r].l].value | a[a[r].r].value;
  28.                 if (a[r].noted) a[r].value = !a[r].value;
  29.         }
  30. }

  31. void get_dp_value(int r) {
  32.         if (!a[r].ok) return;
  33.         if (a[r].type == 1) return; // no left, right sons
  34.         if (a[r].c == '&') {
  35.                 if (a[a[r].r].value != 0) a[a[r].l].ok = 1;
  36.                 if (a[a[r].l].value != 0) a[a[r].r].ok = 1;
  37.         } else {
  38.                 if (a[a[r].r].value != 1) a[a[r].l].ok = 1;
  39.                 if (a[a[r].l].value != 1) a[a[r].r].ok = 1;       
  40.         }
  41.         get_dp_value(a[r].l);
  42.         get_dp_value(a[r].r);
  43. }

  44. int main() {
  45.         char c;
  46.         int id = 0, lasttype = -1; //0 means operator, 1 means number
  47.         while ((c = getchar()) != '\n') { // LN
  48.                 if (c == '\r') continue; // CR
  49.                 if (c == ' ') { // space
  50.                         if (lasttype == 1) {
  51.                                 a[++nodtot] = {1,  0, 0,   0, id, -1, -1};
  52.                                         /*Tip:Type,c,noted,ok,id, l, r*/
  53.                                 nums[++numtot] = nodtot;
  54.                                 stak[++top] = nodtot;
  55.                                 id = 0;
  56.                         }
  57.                 } else if (c == '&' || c == '|' || c == '!') { // operator
  58.                         lasttype = 0;
  59.                         if (c == '!') {
  60.                                 a[stak[top]].noted = 1;
  61.                         } else {
  62.                                 int r = stak[top--];
  63.                                 int l = stak[top--];
  64.                                 a[++nodtot] = {0, c, 0, 0, 0, l, r};
  65.                                 stak[++top] = nodtot;
  66.                         }
  67.                 } else if (c == 'x') { // number first
  68.                         lasttype = 1;
  69.                         id = 0;
  70.                 } else if (c >= '0' && c <= '9') { // number
  71.                         lasttype = 1;
  72.                         id = id * 10 + c - '0';
  73.                 } else assert(0);
  74.         }
  75.         root = stak[top]; // root id
  76.         scanf("%d", &n);
  77.         for (int i = 1; i <= n; ++i) {
  78.                 scanf("%d", &na[i]);
  79.         }
  80.         get_ans(root); // get value
  81.         rootvalue = a[root].value; // root value
  82.         a[root].ok = 1; //first, root change result will change, its right
  83.         get_dp_value(root);
  84.         scanf("%d", &q);
  85.         while (q--) {
  86.                 scanf("%d", &x);
  87.                 if (a[nums[x]].ok) printf("%d\n", !rootvalue); // Can change, change result
  88.                 else printf("%d\n", rootvalue); // Else, it cannot change result
  89.         }
  90.         return 0;
  91. }
复制代码

链接:https://www.luogu.com.cn/record/106777888
总体思路:

先输入字符串,处理成为表达式树,在计算一下整个表达式的结果,接着来处理出如果一个节点发生改变,结果会不会改变,然后,就来回答,能改变就输出相反值,否则输出原结果

只不过,这是错的,因为在 nums[++numtot] 这一行不对,应该是 nums[id] = nodtot, numtot 也就不要了,悲,我就因为这个调了 一整天

现在第一个回复,奖 2 鱼币,因为你缓解了我悲痛的心情!

最佳答案与问题无关!
最佳答案
2023-4-2 17:56:39
代码的问题可能在于输入数字时没有正确处理完毕。具体来说,当读入一个数字时,应该将 lasttype 设置为 1,而不是等到空格时再设置,因为只有在读入数字时才能确定一个节点的类型。因此,可以改成以下代码:

  1. while ((c = getchar()) != '\n') {
  2.     if (c == '\r') continue;
  3.     if (c == ' ') {
  4.         if (lasttype == 1) {
  5.             a[++nodtot] = {1, 0, 0, 0, id, -1, -1};
  6.             nums[++numtot] = nodtot;
  7.             stak[++top] = nodtot;
  8.             id = 0;
  9.         }
  10.         lasttype = -1;
  11.     } else if (c == '&' || c == '|' || c == '!') {
  12.         lasttype = 0;
  13.         if (c == '!') {
  14.             a[stak[top]].noted = 1;
  15.         } else {
  16.             int r = stak[top--];
  17.             int l = stak[top--];
  18.             a[++nodtot] = {0, c, 0, 0, 0, l, r};
  19.             stak[++top] = nodtot;
  20.         }
  21.     } else if (c == 'x') {
  22.         lasttype = 1;
  23.         id = 0;
  24.     } else if (c >= '0' && c <= '9') {
  25.         lasttype = 1;
  26.         id = id * 10 + c - '0';
  27.     } else assert(0);
  28. }
复制代码

另外,也许需要检查一下其他部分是否存在问题,比如变量名和数组下标是否对应等等。

评分

参与人数 1鱼币 +1 收起 理由
myd0313 + 1 鱼C有你更精彩^_^

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-4-2 17:53:03 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 1

使用道具 举报

发表于 2023-4-2 17:55:23 | 显示全部楼层
呵呵。以后超过普及/提高-的题目都不要叫我。
我不是信竞的,我是物竞(悲)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-2 17:56:39 | 显示全部楼层    本楼为最佳答案   
代码的问题可能在于输入数字时没有正确处理完毕。具体来说,当读入一个数字时,应该将 lasttype 设置为 1,而不是等到空格时再设置,因为只有在读入数字时才能确定一个节点的类型。因此,可以改成以下代码:

  1. while ((c = getchar()) != '\n') {
  2.     if (c == '\r') continue;
  3.     if (c == ' ') {
  4.         if (lasttype == 1) {
  5.             a[++nodtot] = {1, 0, 0, 0, id, -1, -1};
  6.             nums[++numtot] = nodtot;
  7.             stak[++top] = nodtot;
  8.             id = 0;
  9.         }
  10.         lasttype = -1;
  11.     } else if (c == '&' || c == '|' || c == '!') {
  12.         lasttype = 0;
  13.         if (c == '!') {
  14.             a[stak[top]].noted = 1;
  15.         } else {
  16.             int r = stak[top--];
  17.             int l = stak[top--];
  18.             a[++nodtot] = {0, c, 0, 0, 0, l, r};
  19.             stak[++top] = nodtot;
  20.         }
  21.     } else if (c == 'x') {
  22.         lasttype = 1;
  23.         id = 0;
  24.     } else if (c >= '0' && c <= '9') {
  25.         lasttype = 1;
  26.         id = id * 10 + c - '0';
  27.     } else assert(0);
  28. }
复制代码

另外,也许需要检查一下其他部分是否存在问题,比如变量名和数组下标是否对应等等。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-2 18:07:07 | 显示全部楼层
额外减小 发表于 2023-4-2 17:55
呵呵。以后超过普及/提高-的题目都不要叫我。
我不是信竞的,我是物竞(悲)

az
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-2 18:09:39 | 显示全部楼层
歌者文明清理员 发表于 2023-4-2 17:56
代码的问题可能在于输入数字时没有正确处理完毕。具体来说,当读入一个数字时,应该将 lasttype 设置为 1, ...

还是25分:
  1. #include <bits/stdc++.h>
  2. using namespace std;

  3. struct Node {
  4.         bool type; // 0 -> operator, 1 -> value
  5.         char c; // if type == 0, it means operator (&, |)
  6.         bool noted; // not -> !
  7.         bool ok; // If this change, result can change
  8.         int id; // number id
  9.         int l, r; //left, right sons
  10.         int value; //eval_value
  11. } a[500001];

  12. int nodtot, nums[1000001], numtot;
  13. int stak[1000001], top, root;
  14. int n, na[1000001], rootvalue, q, x;

  15. void get_ans(int r) {
  16.         if (a[r].type == 1) {
  17.                 a[r].value = na[a[r].id];
  18.                 if (a[r].noted) a[r].value = !a[r].value;
  19.                 return;
  20.         }
  21.         get_ans(a[r].l);
  22.         get_ans(a[r].r);
  23.         if (a[r].c == '&') {
  24.                 a[r].value = a[a[r].l].value & a[a[r].r].value;
  25.                 if (a[r].noted) a[r].value = !a[r].value;
  26.         } else {
  27.                 a[r].value = a[a[r].l].value | a[a[r].r].value;
  28.                 if (a[r].noted) a[r].value = !a[r].value;
  29.         }
  30. }

  31. void get_dp_value(int r) {
  32.         if (!a[r].ok) return;
  33.         if (a[r].type == 1) return; // no left, right sons
  34.         if (a[r].c == '&') {
  35.                 if (a[a[r].r].value != 0) a[a[r].l].ok = 1;
  36.                 if (a[a[r].l].value != 0) a[a[r].r].ok = 1;
  37.         } else {
  38.                 if (a[a[r].r].value != 1) a[a[r].l].ok = 1;
  39.                 if (a[a[r].l].value != 1) a[a[r].r].ok = 1;       
  40.         }
  41.         get_dp_value(a[r].l);
  42.         get_dp_value(a[r].r);
  43. }

  44. int main() {
  45.         char c;
  46.         int id = 0, lasttype = -1; //0 means operator, 1 means number
  47.         while ((c = getchar()) != '\n') { // LN
  48.                 if (c == '\r') continue; // CR
  49.                 if (c == ' ') { // space
  50.                         if (lasttype == 1) {
  51.                                 a[++nodtot] = {1,  0, 0,   0, id, -1, -1};
  52.                                         /*Tip:Type,c,noted,ok,id, l, r*/
  53.                                 nums[++numtot] = nodtot;
  54.                                 stak[++top] = nodtot;
  55.                                 id = 0;
  56.                         }
  57.                         lasttype = -1;
  58.                 } else if (c == '&' || c == '|' || c == '!') { // operator
  59.                         lasttype = 0;
  60.                         if (c == '!') {
  61.                                 a[stak[top]].noted = 1;
  62.                         } else {
  63.                                 int r = stak[top--];
  64.                                 int l = stak[top--];
  65.                                 a[++nodtot] = {0, c, 0, 0, 0, l, r};
  66.                                 stak[++top] = nodtot;
  67.                         }
  68.                 } else if (c == 'x') { // number first
  69.                         lasttype = 1;
  70.                         id = 0;
  71.                 } else if (c >= '0' && c <= '9') { // number
  72.                         lasttype = 1;
  73.                         id = id * 10 + c - '0';
  74.                 } else assert(0);
  75.         }
  76.         root = stak[top]; // root id
  77.         scanf("%d", &n);
  78.         for (int i = 1; i <= n; ++i) {
  79.                 scanf("%d", &na[i]);
  80.         }
  81.         get_ans(root); // get value
  82.         rootvalue = a[root].value; // root value
  83.         a[root].ok = 1; //first, root change result will change, its right
  84.         get_dp_value(root);
  85.         scanf("%d", &q);
  86.         while (q--) {
  87.                 scanf("%d", &x);
  88.                 if (a[nums[x]].ok) printf("%d\n", !rootvalue); // Can change, change result
  89.                 else printf("%d\n", rootvalue); // Else, it cannot change result
  90.         }
  91.         return 0;
  92. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-2 21:28:55 | 显示全部楼层
zhangjinxuan 发表于 2023-4-2 17:53
@tommyyu @ExiaGN001 @额外减小

最近不在线,勿at
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-3 07:17:50 | 显示全部楼层
ExiaGN001 发表于 2023-4-2 21:28
最近不在线,勿at

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-3 18:37:25 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-10 14:28

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表