zoukankan      html  css  js  c++  java
  • CSP-J2 2020 T3,T4 题解

    T3

    观察题目及表达式,建立表达式的二叉树,以运算符为非叶子节点,变量为叶子节点,其中 (&)(|) 运算符有左右两子树, (!) 只有左子树

    发现每次询问需要 (mathcal{O}(log n))(mathcal{O}(1)) 的复杂度,考虑预处理答案

    发现每个变量 (x) 可以或不可以改变答案,观察运算符的性质,可以发现(注:每个子树均能表示一个表达式):

    1. (&) 作为子树根节点时,只要有左子树或右子树的值为 (1) ,则右子树或左子树的值改变能改变该子树的值

    2. (|) 作为子树根节点时,只要有左子树或右子树的值为 (0) ,则右子树或左子树的值改变能改变该子树的值

    3. (!) 作为子树根节点时,其子树改变值能影响该树的值

    第一遍 dfs 求出每个子树(子表达式)的值,第二遍 dfs 按上述性质标记能影响到总表达式值的叶子节点

    对于每次询问,若该变量被标记,即为被取反的总表达式的值,否则就是原表达式的值

    总复杂度 (mathcal{O}(n+q))

    #include<bits/stdc++.h>
    #define forn(i,s,t) for(int i=(s);i<=(t);++i)
    #define form(i,s,t) for(int i=(s);i>=(t);--i)
    using namespace std;
    const int N = 1e6+3;
    char ch[N],tmp[80];
    int n,q,a,b,k,tree[N],L[N],R[N],op[N],rt,sl;    // tree: 若该节点是变量,存变量编号 op:若该节点是符号则存符号 L,R: 左右子树 
    bool val[N];                                    //                                   1表示| 2表示& 0表示!
    int vis[N],x[N];                                // val: 子树求出的值 vis: 是否打标记
    void dfs(int &p) {                              // 建树 (全网最奇葩
    	if(!k) return ;
    	p = ++sl;
    	if(ch[k] == ' '&&k > 0) --k;
    	int a = 0;
    	while(ch[k] != ' ') tmp[++a] = ch[k--];
    	if(tmp[a] == '!') op[p] = 0;
    	else if(tmp[a] == '|') op[p] = 1;
    	else if(tmp[a] == '&') op[p] = 2;
    	else if(tmp[a] == 'x') {
    		int num = 0;
    		form(i,a-1,1) num = num*10+tmp[i]-48;
    		tree[p] = num,val[p] = x[num];
    	}
    	if(tmp[a]!='x') {
    		if(tmp[a] == '!') {
    			dfs(L[p]);
    		} else {
    			dfs(L[p]);
    			dfs(R[p]);
    		}
    	}
    }
    int solve(int p) {                        // 求每个表达式的值
    	if(op[p]!=-1) {
    		if(op[p] == 0) return val[p] = 1^solve(L[p]);
    		else if(op[p] == 1)	return val[p] = solve(L[p])|solve(R[p]);
    		else return val[p] = solve(L[p])&solve(R[p]);
    	} else return val[p];
    }
    void tag(int p,bool kk) {                // 打标记
    	if(op[p]!=-1) {
    		if(op[p] == 0) tag(L[p],1&kk);
    		else if(op[p] == 1) {
    			if(!val[L[p]]) tag(R[p],1&kk);
    			if(!val[R[p]]) tag(L[p],1&kk);
    		} else {
    			if(val[L[p]]) tag(R[p],1&kk);
    			if(val[R[p]]) tag(L[p],1&kk);
    		}
    	} else {
    		vis[tree[p]] = kk;
    	}
    }
    int main() {
    	freopen("expr.in","r",stdin);
    	freopen("expr.out","w",stdout);
    	int len = 0;ch[0] = ' ';
    	forn(i,1,N+1) {
    		ch[++len] = getchar();
    		if(ch[len] == '
    ') break ;
    	}
    	scanf("%d",&n);
    	forn(i,1,n) scanf("%d",&x[i]);
    	memset(tree,-1,sizeof tree);
    	memset(op,-1,sizeof op);
    	k = len,rt = 1;
    	dfs(rt);
    	solve(rt);
    	tag(rt,1);
    	scanf("%d",&q);
    	int pos;
    	forn(i,1,q) {
    		scanf("%d",&pos);
    		printf("%d
    ",vis[pos]?(1^val[rt]):val[rt]);
    	}
    	return 0;
    }
    

    T4

    (f(i,j)) 表示第 (i) 列,第 (j) 行时的最优解

    发现对于每列只能用一个方向取数,用两个数组分别表示向上取和向下取的最优解,

    (g_j) 表示向下取的最优解,有 (g(j) = max {g(j+1),f(i-1,j)} + A_{i,j})

    (h_j) 表示向上取的最优解, 有 (h(j) = max {h(j-1),f(i-1,j)} + A_{i,j})

    则有 (f(i,j) = max {g(j),h(j)})

    总复杂度 (mathcal{O}(n imes m))

    考场代码和上述描述的不太一样,毕竟10min干掉的,最后注意边界

    #include<bits/stdc++.h>
    #define forn(i,s,t) for(int i=(s);i<=(t);++i)
    #define form(i,s,t) for(int i=(s);i>=(t);--i)
    using namespace std;
    typedef long long LL;
    const int N = 1e3+3;
    int n,m;
    LL A[N][N],f[N][N],g[N],h[N],Ans,INF = 1e18;
    int main() {
    	freopen("number.in","r",stdin);
    	freopen("number.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	forn(i,1,n) forn(j,1,m) scanf("%lld",&A[j][i]);
    	forn(i,0,m) forn(j,0,n) f[i][j] = -INF;
    	forn(i,1,m) {
    		if(i == 1) g[0] = 0;
    		else g[0] = -INF;
    		h[n+1] = -INF;
    		forn(j,1,n) g[j] = max(f[i-1][j],g[j-1])+A[i][j];
    		form(j,n,1) h[j] = max(f[i-1][j],h[j+1])+A[i][j];
    		forn(j,1,n) f[i][j] = max(g[j],h[j]);
    	}
    	printf("%lld
    ",f[m][n]);
    	return 0;
    }
    

    PJ AK纪念,TG 心态爆炸纪念

  • 相关阅读:
    基于fis3的组件可视化道路
    前端性能——监控起步
    uploadify使用的一些经验总结
    浏览器加载和渲染HTML的过程(标准定义的过程以及现代浏览器的优化)
    github常见问题【转自百度知道】
    轮播的实现方式
    前端打包构建工具grunt快速入门(大篇幅完整版)
    一些很棒的js代码
    如何高效的编写Verlog HDL——菜鸟版
    基于FPGA的肤色识别算法实现
  • 原文地址:https://www.cnblogs.com/Ax-Dea/p/13943057.html
Copyright © 2011-2022 走看看