吴教授7-9(E-H)

张hao同学同学写的题解,代翻为博客~

E.
LCS模版题,比较测试样例与正确顺序的最长子序列。

for(i = 1; i <= n; i++)
        {
            for(j = 1; j <= n; j++)
            {
                if(a[i] == b[j])
                {
                    dp[i][j] = dp[i-1][j-1] + 1;
                }
                else
                {
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
                }
            }
        }

F.
DFS,尝试从每个点出发,然后dfs,但这里需要再创建一个状态数组来保存已遍历过的情况,然后再在dfs其他点之前判断当前点状态是否为0,

#include<bits/stdc++.h>
using namespace std;
int f[110][110];
int a[110][110];
int dx[4]= {0,0,+1,-1};
int dy[4]= {+1,-1,0,0};
int r,c,t=0,j;
int dfs(int x,int y) {
	if(f[x][y]) return f[x][y];
	for(int i=0; i<4; i++) {
		int xx=x+dx[i];
		int yy=y+dy[i];
		if(xx>=1&&yy>=1&&xx<=r&&yy<=c&&a[xx][yy]<a[x][y])
		f[x][y]=max(f[x][y],dfs(xx,yy)+1);
	}
	return f[x][y];
}
int main() {
	cin>>r>>c;
	for(int i=1; i<=r; i++) {
		for(j=1; j<=c; j++) {
			cin>>a[i][j];
		}
	}
	t=0;
	for(int i=1; i<=r; i++) {
		for(j=1; j<=c; j++) {
			t=max(t,dfs(i,j));
		}
	}
	cout<<t+1;
	return 0;
}

dx,dy用来存放一个点向四个方向移动,同时在引用dfs函数时,i不能事先定义,否则for循环的i与dfs函数里面的i起冲突。

G.
事件 1,任意节点 y 会增加 w − d i s t ( x , y ) 该式子可以转化为:
w − d i s t ( x , y ) = w − ( d [ x ] + d [ y ] − 2 *d [ l c a ( x , y ) ] )
因为 w − d [ x ] 与节点 y无关,可以设sum记录每次的 w − d [ x ] 之和,在询问的时候加上即;
而d[y]仅与节点y有关,因此可以设 num记录事件1的数量,在询问的时候减去num⋅d[y]即可;
对于d[lca(x,y)],可以通过树剖维护,每次将x到根节点的路径上的点加1,这样y到根节点的路径上的点值之和为所有d[lca(x,y)]之和。

事件 2 ,用delta[x]记录事件节点 x在事件 2 2 2中减去的值之和,如果询问得到的x的当前值 val大于 0,那么delta[x]加上val,在求 x当前值时要减去delta[x]。

事件3,根据事件1,2,节点 x的值为sum−num⋅d[x]+2*(x到根路径上的点值之和)−delta[x]

#include<bits/stdc++.h>

#define pi(a) printf("%d\n",a)
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 5e4 + 10;
int head[N], ver[N << 1], Next[N << 1], tot;

struct Seg_Tree {
    struct T {
        int l, r, ans, add;
    } t[N * 4];

    void build(int p, int l, int r) {
        t[p].l = l, t[p].r = r, t[p].ans = t[p].add = 0;
        if (l == r)return;
        int mid = (l + r) >> 1;
        build(p << 1, l, mid);
        build(p << 1 | 1, mid + 1, r);
    }

    void spread(int p) {
        if (t[p].add) {
            t[p << 1].ans += t[p].add * (t[p << 1].r - t[p << 1].l + 1);
            t[p << 1 | 1].ans += t[p].add * (t[p << 1 | 1].r - t[p << 1 | 1].l + 1);
            t[p << 1].add += t[p].add;
            t[p << 1 | 1].add += t[p].add;
            t[p].add = 0;
        }
    }

    void change(int p, int l, int r, int c) {
        if (l <= t[p].l && t[p].r <= r) {
            t[p].add += c;
            t[p].ans += c * (t[p].r - t[p].l + 1);
            return;
        }
        spread(p);
        int mid = (t[p].l + t[p].r) >> 1;
        if (l <= mid)change(p << 1, l, r, c);
        if (r > mid)change(p << 1 | 1, l, r, c);
        t[p].ans = t[p << 1].ans + t[p << 1 | 1].ans;
    }

    int ask(int p, int l, int r) {
        if (l <= t[p].l && r >= t[p].r)return t[p].ans;
        spread(p);
        int mid = (t[p].l + t[p].r) >> 1;
        int val = 0;
        if (l <= mid)val += ask(p << 1, l, r);
        if (r > mid)val += ask(p << 1 | 1, l, r);
        return val;
    }
} sgt;

struct Tree {
    int d[N], fa[N], siz[N], son[N], dfn[N], rnk[N], top[N], num;

    void dfs1(int x, int f) {
        siz[x] = 1, son[x] = 0;
        reps(x) {
            int y = ver[i];
            if (y == f)continue;
            fa[y] = x, d[y] = d[x] + 1, dfs1(y, x), siz[x] += siz[y];
            if (siz[y] > siz[son[x]]) son[x] = y;
        }
    }

    void dfs2(int x, int p) {
        top[x] = p, dfn[x] = ++num, rnk[num] = x;
        if (son[x]) dfs2(son[x], p);
        reps(x) {
            int y = ver[i];
            if (fa[x] == y || y == son[x])continue;
            dfs2(y, y);
        }
    }

    void updr(int x, int y, int v) {
        while (top[x] != top[y]) {
            if (d[top[x]] < d[top[y]])swap(x, y);
            sgt.change(1, dfn[top[x]], dfn[x], v);
            x = fa[top[x]];
        }
        if (d[x] > d[y])swap(x, y);
        sgt.change(1, dfn[x], dfn[y], v);
    }

    int quer(int x, int y) {
        int ans = 0;
        while (top[x] != top[y]) {
            if (d[top[x]] < d[top[y]])swap(x, y);
            ans += sgt.ask(1, dfn[top[x]], dfn[x]);
            x = fa[top[x]];
        }
        if (d[x] > d[y])swap(x, y);
        ans += sgt.ask(1, dfn[x], dfn[y]);
        return ans;
    }


    inline void init(int n, int r) {
        d[r] = 1, num = 0, dfs1(r, 0), dfs2(r, r), sgt.build(1, 1, n);
    }
} tr;

int d[N], sum, num, n, m, T;

inline void init() {
    tot = sum = num = 0;
    repi(i, 1, n)head[i] = d[i] = 0;
}

inline void add(int x, int y) {
    ver[++tot] = y;
    Next[tot] = head[x];
    head[x] = tot;
}

inline int ask(int x) {
    return sum - tr.d[x] * num + 2 * tr.quer(x, 1) - d[x];
}

int main() {
    T = qr();
    while (T--) {
        n = qr(), m = qr();
        init();
        repi(i, 1, n - 1) {
            int x = qr(), y = qr();
            add(x, y), add(y, x);
        }
        tr.init(n, 1);
        while (m--) {
            int op = qr(), x = qr();
            if (op == 1) {
                int w = qr();
                sum += w - tr.d[x], num++;
                tr.updr(x, 1, 1);
            } else if (op == 2) {
                int val = ask(x);
                if (val > 0)d[x] += val;
            } else
                pi(ask(x));
        }
    }
    return 0;
}

H.

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+7;
int a[maxn];
int f(int x) {
	int i;
	for(i=2; i*i<=x; i++) {
		if(x%i==0)
			return 0;
	}
	return 1;
}
int main() {
	int a,i,j,max,s=0;
	while(cin>>a) {
		s=0;
		if(a==0)
			return 0;
		for(i=3; i<=a; i+=2) {
			if(f(i)==1&&f(a-i)==1) {
				printf("%d = %d + %d\n",a,i,a-i);
				s++;
				break;
			}
		}
	}
	if(!s)
		cout<<" Goldbach's conjecture is wrong."<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LuckyInn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值