码迷,mamicode.com
首页 > 其他好文 > 详细

P7073 表达式(expr)

时间:2020-11-19 12:33:47      阅读:8      评论:0      收藏:0      [点我收藏+]

标签:bre   tin   const   size   names   clu   ret   整数   ons   

说在前面

考场上的我是真的逊,expr代码都写出来了结果没有更新到D:/submit而爆零。

题意简述

给你一个后缀表达式\(s\),只有&,|,!运算,有\(n\)个变量,为\(x_1,x_2,\cdots x_n\),其中任意\(x_i \in \{0,1\}\),给\(x_i\)的初值,\(q\)个操作,每次操作:

给一个整数\(a\),要求将\(x_a\)的值取反,求这个表达式的值。

数据范围:

  • \(20\%\) 运算仅有&|
  • 另外\(30\%\) \(|s| \le 1000,q \le 1000,n \le 1000\)
  • 另外\(20\%\),变量初值全部相同。
  • \(100\%\) \(1 \le |s| \le 1 \times 10 ^ 6,1 \le q \le 1 \times 10 ^ 5,2 \le n \le 1 \times 10 ^ 5\)

简单口胡

  • \(20\%\) 每次进行表达式运算,\(\mathcal{O}(nq)\),逊

部分分只会这一个

正解:考虑对\(x_i\)取反是否会影响整个式子的值,先建一个表达式树,对于每个节点,它和它的子树也是一个表达式,其中对于非叶节点,这个节点是一个运算符,这个表达式的值为\(L(x) \operatorname{opt} R(x)\),\(\operatorname{opt}\) 为这个运算符,\(L(x)\)\(R(x)\)为这个节点的左子树表达式的值和右子树表达式的值。

分类讨论:

  • 如果这个节点是叶子,啥事没有
  • 如果这个节点是&,那么:
    如果\(L(x) = 0\),那么这个表达式的值肯定为\(0\),也就是说\(R(x)\)对答案没有贡献,给右子树里的所有节点打上标记。

\(R(x) = 0\)同理。

  • 如果这个节点是|,那么:
    如果\(L(x) = 1\),那么这个表达式的值肯定为\(1\),也就是说\(R(x)\)对答案没有贡献,给右子树里的所有节点打上标记。

\(R(x) = 1\)同理。

于是这题就没了,\(\text{dfs}\)打好标记和计算一开始表达式的答案\(ans\),对于每一个询问,如果这个询问有标记,代表对其取反对\(ans\)没有变化,否则输出\(!ans\)

大概是\(\mathcal{O}(n)\)

# include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 5;
int q[N],tot;
int n,val[N / 10];

int ch[N][2];
bool C[N / 10];
int Opt[N];

stack <int> s;

int Get(string st,int l)
{
    int ans = 0;
    int len = st.size();
    for(int i = l; i < len; i++)
    {
        ans = ans * 10 + st[i] - ‘0‘;
    }
    return ans;
}

int key(char opt)
{
    if(opt == ‘|‘) return -1;
    if(opt == ‘&‘) return -2;
    if(opt == ‘!‘) return -3;
}

void Input(void)
{
    string st;
    while(cin >> st)
    {
        if(isdigit(st[0]))
        {
            break;
        }
        else
        {
            if(st[0] == ‘x‘)
            {
                int num = Get(st,1);
                // printf("num = %d\n",num);
                q[++tot] = num;
            }
            else
            {
                q[++tot] = key(st[0]);
            }
        }
    }
    n = Get(st,0);
    // printf("n = %d\n",n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d",&val[i]);
    }
    return;
}

int dfs(int root)
{
    if(root <= n) return val[root];
    if(Opt[root] == -3) return !dfs(ch[root][0]);
    if(Opt[root] == -1)  // or
    {
        int ans1 = dfs(ch[root][0]),ans2 = dfs(ch[root][1]);
        if(ans1 == 1) 
            C[ch[root][1]] = 1;
        if(ans2 == 1) 
            C[ch[root][0]] = 1;
        return ans1 | ans2;
    }
    else
    {
        if(Opt[root] == -2) // and
        {
            int ans1 = dfs(ch[root][0]),ans2 = dfs(ch[root][1]);
            if(ans1 == 0) 
                C[ch[root][1]] = 1;
            if(ans2 == 0)
                C[ch[root][0]] = 1;
            return ans1 & ans2;
        }
    }
}

void pushup(int root)
{
    if(ch[root][0]) C[ch[root][0]] |= C[root];
    if(ch[root][1]) C[ch[root][1]] |= C[root];
    if(ch[root][0]) pushup(ch[root][0]);
    if(ch[root][1]) pushup(ch[root][1]);
    return;
}

int main(void)
{
    Input();
    int cur = n;
    for(int i = 1; i <= tot; i++)
    {
        if(q[i] > 0)
        {
            s.push(q[i]);
        }
        else
        {
            if(q[i] == -3)
            {
                int a1 = s.top();s.pop();
                Opt[++cur] = -3;
                ch[cur][0] = a1;
                s.push(cur);
                continue;
            }
            int a1 = s.top();s.pop();
            int a2 = s.top();s.pop();
            Opt[++cur] = q[i];
            ch[cur][0] = a1,ch[cur][1] = a2;
            s.push(cur);
        }
    }
    // printf("cur = %d\n",cur);
    int now = dfs(cur);
    pushup(cur);
    int test;
    scanf("%d",&test);
    while(test--)
    {
        int x;
        scanf("%d",&x);
        printf("%d\n",C[x] ? now : !now);
    }
    return 0;
}

P7073 表达式(expr)

标签:bre   tin   const   size   names   clu   ret   整数   ons   

原文地址:https://www.cnblogs.com/luyiming123blog/p/P7073.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!