7.26

A

并查集维护,时间复杂度我写的貌似不大对,先鸽一鸽

B

敦爷:\(w\)是这个区间的最大值当且仅当他是这个区间内最大的

我们发现结合昨天课件内的并查集

发现我们每次不断合并的本质是把所有\(<=w\)的边连上

我们将这条边连接的两个连通块连到一起时,连个联通块的大小就是贡献

我们把边权按照大小排序

一条条的加进去

那么总的贡献就是\(w*size(a) *size(b)\)

当然,这只是一次合并的总的贡献

这时候我们发现单个元素的贡献是可以顺便维护的

即使对于\(a\)中联通块的元素

每个贡献都有\(w*size(b)\)

\(b\)同理

这只是一条链的情况

我们考虑树上该怎么做

点权转成边权

同理每次考虑合并每个链连通的两个联通块

我们要按秩合并,不要路径压缩

每个并查集的根节点都要维护两个东西

首先是当前子树的\(tag\)

因为上面说的这个连通块内的每个元素都是有贡献的

我们在根节点上打上\(tag\)后面下放一遍记好了

我们想一下

\(a\),\(b\)两个联通块合并我们假设\(a\)的\(size\)比较小一些

那个应该是

\(tag_a += w*size_b\)

\(tag_b+=w*size_a\)

但是我们发现,我们把\(a\)并到\(b\)上之后

原本在\(b\)上的\(tag\)对\(a\)是没有效果的,我们下放的时候却会计算到里面

所以我们要让这一部分的贡献减去

\(tag_a -=tag_b\)

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#define LL long long using namespace std;
const int N = 4e5 + 311;
int n,m,tot;
LL ans[N];
int fa[N],size[N];
LL w[N];
vector <int> G[N];
struct edge{
int from;
int to;
LL data;
}e[N << 1];
inline int getf(int x){
return x == fa[x] ? x : getf(fa[x]);
}
inline bool cmp(edge x,edge y){
return x.data < y.data;
}
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
inline void dfs(int x,int f){
ans[x] += ans[f];
for(int i = 0;i < (int)G[x].size();++i){
int y = G[x][i];
if(y == f) continue;
dfs(y,x);
}
}
int main(){
n = read();
for(int i = 2;i <= n;++i){
int x = read();
e[++tot] = (edge){i,x,0};
}
for(int i = 1;i <= n;++i) w[i] = read();
for(int i = 1;i <= n + 13;++i) fa[i] = i,size[i] = 1;
for(int i = 1;i <= tot;++i) e[i].data = max(w[e[i].from],w[e[i].to]);
// for(int i = 1;i <= tot;++i){
// printf("%d %d %lld\n",e[i].from,e[i].to,e[i].data);
// }
sort(e + 1,e + tot + 1,cmp);
for(int i = 1;i <= tot;++i){
int x = getf(e[i].from),y = getf(e[i].to);
if(size[x] > size[y]) swap(x,y);
if(x == y) continue;
// printf("%d %d %lld %lld\n",x,y,ans[x],ans[y]);
G[y].push_back(x);
ans[y] += e[i].data * size[x];
ans[x] += e[i].data * size[y];
ans[x] -= ans[y];
size[y] += size[x];
fa[x] = y;
}
dfs(getf(1),0);
for(int i = 1;i <= n;++i) printf("%lld ",ans[i] + w[i]);
return 0;
}

C

问你删除循序的题目

一定要先考虑那个数最后被删掉

我们枚举那个数最后被删掉

如果一个数最后被删掉

那么这个数两边的数永远也不会相邻

我们发现如果我们已经处理出来了

左边的方案数\(A\),右边的方案数\(B\)

那么答案就是\(C_{A + B}^A\)

我们考虑暴力DP

我们设\(f_{l,r,lx,rx}\)表示区间\([l,r]\),且满足左端点不等于\(l_x\),右端点不等于\(r_x\)时的答案

转移我们就枚举区间分裂位置\(k\)

\(f_{l,r,lx,rx} = \sum _{i = l}^rC_{r - l}^{k - l}*f_{l,k - 1,lx,a_{k}} * f_{k + 1,r,a_k,r_x}\)

注意要乘一下组合数

因为这里对与两种不同的合法方案

将他们合并顺序不同可能会影响答案

而合并的总的可能循序就是一共\(r - l\)个位置,有\(k - l\)个位置在操作左边

这样就得到了一个\(n^5\)的做法

之后我们发现这个做法有点蠢

因为对于一个确定\([l,r ]\),\(lx,rx\)一定是确定的

因为你想一下我们DP过程,是钦定一个位置最后选

那么这时候就被卡住了

分裂后的区间的限制

也就是说\([l,r]\)的限制一定是我们强制了\(a_{l -1}\)和\(a_{r + 1}\)得到的

之后发现\(r_x\)和\(l_x\)这一维是固定的,不需要枚举

那么,DP方程就可以简化为

\(f_{l,r} = \sum_{k = l}^rC_{r -l}^{k - 1}*f_{l,k - 1}*_{k + 1,r}\)

\(k\)就是我们要枚举的子区间最后一个删除的位置

很明显转移要有\(a_{k}!=a_{l - 1}\)和\(a_{k}!= a_{r + 1}\)

另外,为了防止\(f_{l,k - 1}\)中\(l > k - 1\)的情况导致漏掉答案

初始化时\(f_{i + 1,i} = 1\)

也是必要的

#include<iostream>
#include<cctype>
#include<queue>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cstdio>
#include<stack>
#define LL long long
const int N = 505;
const LL mod = 998244353;
using namespace std;
LL f[N][N];
LL fac[N],inv[N];
int n;
int a[N];
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
inline LL quick(LL a,LL b){
LL res = 1;
while(b){
if(b & 1) res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
inline LL C(int x,int y){
return fac[x] * inv[y] % mod * inv[x - y] % mod;
}
inline LL mo(LL x){
if(x >= mod) x -= mod;
return x;
}
int main(){
scanf("%d",&n);
fac[0] = inv[0] = fac[1] = inv[1] = 1;
for(int i = 2;i <= n;++i){
fac[i] = fac[i - 1] * i % mod;
inv[i] = quick(fac[i],mod - 2);
}
for(int i = 1;i <= n;++i) a[i] = read();
for(int i = 1;i < n;++i)
if(a[i] == a[i + 1]){
printf("0\n");
return 0;
} for(int i = 1;i <= n;++i) f[i][i] = f[i][i - 1] = 1;
f[n + 1][n] = 1;
a[0] = a[n + 1] = -1;
for(int len = 2;len <= n;++len){
for(int l = 1;l + len - 1 <= n;++l){
int r = l + len - 1;
for(int k = l;k <= r;++k){
if(a[k] != a[l - 1] && a[k] != a[r + 1])
f[l][r] = mo(f[l][r] + C(r - l,k - l) * f[l][k - 1] % mod * f[k + 1][r]) % mod;
}
}
}
printf("%lld\n",f[1][n]);
return 0;
}

ZR7.26的更多相关文章

  1. CSharpGL(26)在opengl中实现控件布局/渲染文字

    CSharpGL(26)在opengl中实现控件布局/渲染文字 效果图 如图所示,可以将文字.坐标轴固定在窗口的一角. 下载 CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入( ...

  2. C#开发微信门户及应用(26)-公众号微信素材管理

    微信公众号最新修改了素材的管理模式,提供了两类素材的管理:临时素材和永久素材的管理,原先的素材管理就是临时素材管理,永久素材可以永久保留在微信服务器上,微信素材可以在上传后,进行图片文件或者图文消息的 ...

  3. grep-2.26 sed-4.2.2 awk-4.1.4 wget-1.18 pcregrep-8.39 pcre2grep-10.22 for windows 最新版本静态编译

    -------------------------------------------------------------------------------------------- grep (G ...

  4. TMS320F28027/26/23/22/21/20芯片解密单片机破解原理!

    TMS320F28027/26/23/22/21/20芯片解密单片机破解 TMS320F2802系列芯片解密型号: TMS320F28027F.TMS320F280270.TMS320F28027.T ...

  5. [.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit

    [.net 面向对象程序设计进阶] (26) 团队开发利器(五)分布式版本控制系统Git——图形化Git客户端工具TortoiseGit 读前必备: 接上篇: 分布式版本控制系统Git——使用GitS ...

  6. 编写高质量代码:改善Java程序的151个建议(第2章:基本类型___建议26~30)

    建议26:提防包装类型的null值 我们知道Java引入包装类型(Wrapper Types)是为了解决基本类型的实例化问题,以便让一个基本类型也能参与到面向对象的编程世界中.而在Java5中泛型更是 ...

  7. 背水一战 Windows 10 (26) - XAML: x:DeferLoadStrategy, x:Null

    [源码下载] 背水一战 Windows 10 (26) - XAML: x:DeferLoadStrategy, x:Null 作者:webabcd 介绍背水一战 Windows 10 之 XAML ...

  8. 新手指南: Linux 新手应该知道的 26 个命令

    当你进入了 Linux 的世界,在下载.安装 了某个 Linux 发行版,体验了 Linux 桌面并安装了一些你喜爱和需要的软件之后,应该去了解下 Linux 真正的魅力所在:命令行.每一个 Linu ...

  9. Java编程中“为了性能”需做的26件事

    1.尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面: (1)控制资源的使用,通过线程同步来控制 ...

随机推荐

  1. 初探postman

    第一种:安装postman 扩展程序 第二种:本地 安装postman 登陆进来postman的界面 发送第一个postman请求 将请求保存到集合 未完,待续...

  2. 【JZOJ4833】【NOIP2016提高A组集训第3场10.31】Mahjong

    题目描述 解法 搜索. 代码 #include<stdio.h> #include<iostream> #include<string.h> #include< ...

  3. working copy is not up-to-date

    解决方法:  在相应文件上,单击选择team,然后选择先更新,然后再提交.这样就好了.

  4. 《js高级程序设计》6.1.1-6.1.3——数据属性、访问器属性

    数据属性:该属性包含了一个数据值的位置,它包含了4个描述行为的特性:1. [[Configurable]]:表示是否能通过delete删除属性从而重新定义属性,能否修改属性的特性,能否把属性修改为访问 ...

  5. C#中的字段,常量,属性与方法

    以前是学C++的,初次学微软的C#头都大了.什么字段,常量,属性,方法......微软把别人的东西拿来糅合在C#里,弄成了一个“大杂烩”.其实,说到底,“字段”不就是“变量”吗,所谓的“方法”不就是“ ...

  6. linux下arm平台Qt编译环境搭建与解析

    一.概述:      我们知道QTcreator.这仅仅是个IDE,他包含了一个编译器--qmake.这两者的关系与codeblocks和g++的关系一样,首先要明确这些.      而我们在linu ...

  7. 一维数组的初始化及遍历 Day06

    package com.sxt.arraytest1; import java.util.Arrays; /* * 一维数组 */ public class ArrayTest2 { public s ...

  8. 2015 Objective-C 三大新特性

    http://www.cocoachina.com/ios/20150617/12148.html Overview 自 WWDC 2015 推出和开源 Swift 2.0 后,大家对 Swift 的 ...

  9. mysql数据库之mysql下载与设置

    下载和安装mysql数据库 mysql为我们提供了开源的安装在各个操作系统上的安装包,包括ios,liunx,windows. mysql的安装,启动和基础配置-------linux版本 mysql ...

  10. 唯一索引与非唯一索引区别(UNIQUE INDEX, NON-UNIQUE INDEX)

    索引是我们经常使用的一种数据库搜索优化手段.适当的业务操作场景使用适当的索引方案可以显著的提升系统整体性能和用户体验.在Oracle中,索引有包括很多类型.不同类型的索引适应不同的系统环境和访问场景. ...