首页 > 其他分享 >P7324 [WC2021] 表达式求值 题解

P7324 [WC2021] 表达式求值 题解

时间:2024-01-28 23:00:15浏览次数:21  
标签:ch lc int 题解 P7324 read str 求值 define

题目链接

点击打开链接

题目解法

不错的题

首先建出表达式树
说实话我一开始不知道怎么建,但看了代码之后就懂了
这里简单说一下:假如要对区间 \([l,r]\) 建树,分 \(E_r=)\) 和 \(E_r\neq )\) 的情况

  • \(E_r=)\),找到匹配的左括号,递归下去建树
  • \(E_r\neq )\),\(r\) 可以作为单独的一个叶子,于是递归到 \([l,r-2]\) 和 \([r,r]\) 建树

\(O(n|E|m)\) 是显然的
首先肯定是拆成数组的每一位做
里面做一遍树形 \(dp\) 即可,即 \(f_{i,j}\) 表示在结点 \(i\) 的结果为第 \(j\) 个数组的值,不难转移

考虑如何优化
这一步优化很巧妙,枚举最后的结果为第 \(x\) 个数组,记第 \(x\) 个数组当前位的值为 \(v\)(如果数值相同可以按照字典序排),那么最后的方案数只与比 \(v\) 大的集合有关,不妨枚举这个集合为 \(S\)
不难得到树形 \(dp\) 为 \(f_{i,0/1/2}\) 表示在结点 \(i\) 的结果为 \(<v/=v/>v\) 的方案数,转移显然
最后值为 \(v\) 的方案数即为 \(f_{rt,1}\)
但这样的复杂度仍是 \(O(m2^m|E|)\),不能通过

考虑进一步优化,即如何不枚举 \(x\)
这里我们把最后的值类似地转成差分的形式,即我们改变最后需要求得的答案:最终结果 $\ge $ 在集合 \(S\) 中的方案数
这样只要令 \(f_{i,0/1}\) 表示结点 \(i\) 的结果为 \(<v/\ge v\) 的方案数
复杂度就降为了 \(O(2^m|E|)\)

最后统计答案显然
时间复杂度为 \(O(2^m|E|+nm\log m)\)

#include <bits/stdc++.h>
#define F(i,x,y) for(int i=(x);i<=(y);i++)
#define DF(i,x,y) for(int i=(x);i>=(y);i--)
#define ms(x,y) memset(x,y,sizeof(x))
#define SZ(x) (int)x.size()-1
#define all(x) x.begin(),x.end()
#define pb push_back
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> pii;
template<typename T> void chkmax(T &x,T y){ x=max(x,y);}
template<typename T> void chkmin(T &x,T y){ x=min(x,y);}
inline int read(){
    int FF=0,RR=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
    for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
    return FF*RR;
}
const int N=50010,M=10,P=1e9+7;
int n,m,a[M][N],id[M],g[1<<M];
char str[N];
int stk[N],top,brc[N];
int op[N],ind[N],lc[N],rc[N],idx;
int Get(int p){ if(str[p]=='>') return 1;if(str[p]=='<') return 0;return 2;}
int build(int l,int r){
    if(brc[r]){
        if(brc[r]==l) return build(l+1,r-1);
        int p=++idx;op[p]=Get(brc[r]-1);
        rc[p]=build(brc[r]+1,r-1),lc[p]=build(l,brc[r]-2);
        return p;
    }
    int p=++idx;
    if(l==r){ ind[p]=str[l]-48;return p;}
    op[p]=Get(r-1),rc[p]=build(r,r),lc[p]=build(l,r-2);
    return p;
}
int State,f[N][2];
inline void inc(int &x,int y){ x+=y;if(x>=P) x-=P;}
void dfs(int u){
    if(!lc[u]){ f[u][State>>ind[u]&1]=1;return;}
    dfs(lc[u]),dfs(rc[u]);
    if(op[u]==1||op[u]==2) F(i,0,1) F(j,0,1) inc(f[u][max(i,j)],1ll*f[lc[u]][i]*f[rc[u]][j]%P);
    if(!op[u]||op[u]==2) F(i,0,1) F(j,0,1) inc(f[u][min(i,j)],1ll*f[lc[u]][i]*f[rc[u]][j]%P);
}
int main(){
    n=read(),m=read();
    F(i,0,m-1) F(j,1,n) a[i][j]=read();
    scanf("%s",str+1);
    int len=strlen(str+1);
    F(i,1,len){
        if(str[i]=='(') stk[++top]=i;
        if(str[i]==')') brc[i]=stk[top],brc[stk[top]]=i,top--;
    }
    ms(ind,-1);
    int rt=build(1,len);
    F(S,0,(1<<m)-1){
        ms(f,0);State=S,dfs(rt);
        g[S]=f[rt][1];
    }
    int ans=0;
    F(i,1,n){
        F(j,0,m-1) id[j]=j;
        sort(id,id+m,[&](int x,int y){ return a[x][i]>a[y][i];});
        int St=0;inc(ans,1ll*g[(1<<m)-1]*a[id[m-1]][i]%P);
        F(j,0,m-2) St|=1<<id[j],inc(ans,1ll*g[St]*(a[id[j]][i]-a[id[j+1]][i])%P);
    }
    printf("%d\n",ans);
    return 0;
}

标签:ch,lc,int,题解,P7324,read,str,求值,define
From: https://www.cnblogs.com/Farmer-djx/p/17993588

相关文章

  • ABC338D 题解
    赛时怎么连这题都不会。再不练练思维真的就连普及题都不会做了啊。Solution题目来源:ABC338D(inAtcoder|in洛谷)。不妨先考虑应该断掉哪条边。首先我们发现,仅断掉一条边并不会让两个结点不可达,只会让我们从一个结点绕更远的路到达目标结点。如果我们要从结点\(u\)前往结点......
  • CF1070H 题解
    思路我们第一眼看题就发现每个字符串的长度在只有\(8\)。我们需要判断的是某个字符串是不是前面字符串的子串,因为长度太小,所以可以把字符串的每一个子串放到map里,再用一个map判断一个子串是否在当前字符串出现过,出现过就不能重复记。最后在用一个map记录一下每个子串对应......
  • CF1472F 题解
    前言只要题目给了图,你就要画图。思路首先,我们要明确一点:一个矩形,如果里面不存在任何被覆盖的方格,那么这个矩形是绝对可以被覆盖的。如果现在有一个点被覆盖了。那么必定要有一个长方形从这个点下方往后。然后继续在上方接长方形继续往后。直到出现了一个新节点被覆盖。......
  • 第一周题解
    第一周周报这一周是寒假训练的第一周,训练内容主要就是做牛客上的题单还有比赛,牛客上的题单还是比较痛苦的,因为牛客压根看不了测试用例,导致我事后想知道错的例子是什么都看不了。做第一题第二题还有倒数第三题有一两个例子一直都过不去。检查了很久的代码,一直是差一两个例子,就老是......
  • P4145 上帝造题的七分钟 2 / 花神游历各国 题解
    题目链接:上帝造题的七分钟2/花神游历各国差不多的题:[YnoiEasyRound2023]TEST_69注意到对某个点来说暴力单点即为反复的:\(x=\sqrt{x}\),最终为\(1\),根据\(master\)主定理可知,跟\(veb\)树分析差不多的,复杂度为:\(O(\log{\log{V_{max}}})\)。不懂的可以去学学这篇文章。那......
  • 洛谷题解-[ARC001B] リモコン
    https://www.luogu.com.cn/problem/AT_arc001_2题目描述 输入格式无输出格式无题意翻译题目描述:高桥君要调整空调的设定温度。现在的设定温度是A度,而他想调到B度。空调遥控器按一次可以:上调或下调1度上调或下调5度上调或下调10度高桥君想求出从A调到B度的最小......
  • P1197 [JSOI2008] 星球大战 题解
    P1197[JSOI2008]星球大战题解题目链接P1197[JSOI2008]星球大战简要思路看完题目的第一印象是——连通性。图论中判断连通性很容易想到并查集,但是并查集只支持合并和查询,并不支持删除,怎么办呢?考虑逆向思维,把删点的过程倒过来,看成加点和连边,那么此题就可以非常方便的用并......
  • 洛谷题解-P1938 [USACO09NOV] Job Hunt S
    https://www.luogu.com.cn/problem/P1938题目描述Bessieisrunningoutofmoneyandissearchingforjobs.FarmerJohnknowsthisandwantsthecowstotravelaroundsohehasimposedarulethathiscowscanonlymakeD(1<=D<=1,000)dollarsinac......
  • ATtokiomarine2020E O(rand) 题解
    题目链接点击打开链接题目解法首先,\(S\)一定要是\(T\)的子集先筛出符合条件的\(a_i\),即满足\(S\subseteqa_i\subseteqT\)令\(dif\)为\(T-S\),定义数\(x\)覆盖第\(y\)位为二进制下\(x\)的第\(y\)位为\(1\)现在的问题变成了找到大小\(\lek\)的\(\{a_i\}......
  • 洛谷题解-P2888 [USACO07NOV] Cow Hurdles S (Floyd)
    https://www.luogu.com.cn/problem/P2888题目描述FarmerJohnwantsthecowstoprepareforthecountyjumpingcompetition,soBessieandthegangarepracticingjumpingoverhurdles.Theyaregettingtired,though,sotheywanttobeabletouseaslittleene......