CF 463A && 463B 贪心 && 463C 霍夫曼树 && 463D 树形dp && 463E 线段树
http://codeforces.com/contest/462
要求是否全部的字符都挨着偶数个'o'
#include <cstdio>
using namespace std;
char maz[][];
int n;
int cnt[][];
const int dx[]={,,-,};
const int dy[]={,-,,};
int main(){
scanf("%d",&n);
gets(maz[]);
for(int i=;i<n;i++){
gets(maz[i]);
}
for(int i=;i<n;i++){
for(int j=;j<n;j++){
if(maz[i][j]=='o'){
for(int k=;k<;k++){
int nx=i+dx[k];
int ny=j+dy[k];
if(nx<n&&ny<n&&nx>=&&ny>=){cnt[nx][ny]++;}
}
}
}
}
for(int i=;i<n;i++){
for(int j=;j<n;j++){
if(cnt[i][j]&){puts("NO");return ;}
}
}
puts("YES");
return ;
}
贪心
#include <cstdio>
#include <algorithm>
using namespace std;
long long n,k;
long long cnt[];
char maz[];
int main(){
scanf("%I64d%I64d",&n,&k);
gets(maz);
gets(maz);
for(int i=;i<n;i++)cnt[maz[i]-'A']++;
sort(cnt,cnt+);
long long ans=;
for(int i=;i>=;i--){
if(cnt[i]>=k){
ans+=k*k;
k=;
}
else {
k-=cnt[i];
ans+=cnt[i]*cnt[i];
}
if(k==)break;
}
printf("%I64d\n",ans);
return ;
}
题解意思:
这是一道霍夫曼编码的反问题,把所有边权取反就是霍夫曼树问题,详细证明请看算法导论,大概证明一下:
可以把每次的拿来拆分的每一段的都作为树上的节点,长度为1的值必然是叶节点,会在统计一次后被抛出,这时父节点权值则是子节点权值之和,而且必然是一颗二叉树,这与题目是符合的,也就是说深度越大的叶节点加和的次数越多,那么把最大的那两个节点先放在树里,那么它们的父节点就拥有两个节点之和的性质,那么再添加次大的,如此构建就形成了整棵最优树,(算法导论可以严格证明这是棵最优树,通过反证法),于是除了最大的两个点加了n次,其余的点分别加了n-1,n-2,....2次
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=;
int n;
long long a[maxn];
int main(){
scanf("%d",&n);
long long ans=,sum=;
for(int i=;i<n;i++){scanf("%I64d",a+i);sum+=a[i];}
sort(a,a+n);
ans=sum;
for(int i=;i<n;i++){
ans+=sum;
sum-=a[i-];
}
printf("%I64d\n",ans);
return ;
}
D:Appleman and Tree
树形dp
这是一道树形dp,我一开始想到奇怪的地方去了,什么连通域之类的
对每个点,dp记录使其的所有子树成为单黑或纯白的方式,最后再加上自身的黑/白属性
具体来说
初始化:子树单黑=0,子树纯白=1
单黑=现有单黑*子树纯白+子树单黑*现有纯白
纯白=现有纯白*子树纯白
然后加入自身的属性
如果自身为黑,那么单黑=子树纯白(现有黑:切掉所有子节点成为0)
如果自身为白,那么纯白*=子树纯白(切掉本身使得孤立的方式更多)
#include<cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=;
const long long mod= ;
long long dp[maxn][];
int color[maxn];
vector<int> G[maxn];
bool vis[maxn];
void dfs(int s){
dp[s][]=;
dp[s][]=;
vis[s]=true;
for(int i=;i<G[s].size();i++){
int t=G[s][i];
if(vis[t])continue;
dfs(t);
dp[s][]=(dp[s][]*dp[t][]+dp[s][]*dp[t][])%mod;
dp[s][]=dp[s][]*dp[t][]%mod;
}
if(color[s]==){
dp[s][]=dp[s][];
}
else dp[s][]+=dp[s][];
dp[s][]%=mod;
dp[s][]%=mod;
}
int main(){
int n;
scanf("%d",&n);
for(int i=;i<n;i++){
int temp;
scanf("%d",&temp);
G[temp].push_back(i);
}
for(int i=;i<n;i++)scanf("%d",color+i);
dfs();
printf("%I64d\n",dp[][]);
return ;
}
E:Appleman and a Sheet of Paper
线段树
翻折,当长度>len/2的时候那么就反向翻折,这时候相当于反向了一次,需要反着来统计
看上去思路很清晰但是很麻烦
#include<cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=;
const int maxnode=;
long long w[maxnode];
int cur,s,e,len,n,q;
int num(int i){//返回正确的标号,传入的是从开始的端点所需经过距离
if(cur==){return s+i;}
return e-i;
}
void update(int k,int d){//更新线段树
int tk=k;
k+=n-;
w[k]+=d;
while(k>){
k=(k-)/;
w[k]+=d;
}
}
void inv(int l){//翻转
int tl;
if(l*>len){tl=len-l;cur^=;}//翻转统计的同时就要反向更新了
else tl=l;
for(int i=;i<tl;i++){
int td=num(tl*--i);
int td2=num(i);
update(td,w[td2+n-]);
update(td2,-w[td2+n-]);
}
if(cur)e-=tl;else s+=tl;
len=e-s+;
}
long long query(int a,int b,int k,int l,int r){
if(r<=a||l>=b||l>=r)return ;
if(a<=l&&r<=b){
return w[k];
}
else {
long long v1=query(a,b,k*+,l,(l+r)/);
long long v2=query(a,b,k*+,(l+r)/,r);
return v1+v2;
}
}
int main(){
scanf("%d%d",&n,&q);int tn=n,ttn=n;n=;
while(tn>){n<<=;tn>>=;}
for(int i=;i<ttn;i++)update(i,);
s=;e=ttn-;len=ttn;
while(q--){
int op;
scanf("%d",&op);
if(op==){
int l;
scanf("%d",&l);
inv(l);
}
else{
int l,r;
scanf("%d%d",&l,&r);
if(cur){
l=num(l-);//这里卡我半天因为题目给的是从s开始的序号所以从e开始就要+1,传进的参数要-1
r=num(r-);
}
else {
l=num(l);
r=num(r);
}
if(l>r)swap(l,r);
long long ans=query(l,r,,,n);
printf("%I64d\n",ans);
} }
}
CF 463A && 463B 贪心 && 463C 霍夫曼树 && 463D 树形dp && 463E 线段树的更多相关文章
- Alink漫谈(十六) :Word2Vec源码分析 之 建立霍夫曼树
Alink漫谈(十六) :Word2Vec源码分析 之 建立霍夫曼树 目录 Alink漫谈(十六) :Word2Vec源码分析 之 建立霍夫曼树 0x00 摘要 0x01 背景概念 1.1 词向量基础 ...
- 赫夫曼\哈夫曼\霍夫曼编码 (Huffman Tree)
哈夫曼树 给定n个权值作为n的叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权值较大的结点离 ...
- C# 霍夫曼二叉树压缩算法实现
知道有的人比较懒,直接贴全部代码. 一开始一次性Code完了压缩部分代码.只调试了2,3次就成功了. 一次性写150行代码,没遇到什么bug的感觉还是蛮爽的. 写解压代码,才发现压缩代码有些细节问题. ...
- 基于python的二元霍夫曼编码译码详细设计
一.设计题目 对一幅BMP格式的灰度图像(个人证件照片)进行二元霍夫曼编码和译码 二.算法设计 (1)二元霍夫曼编码: ①:图像灰度处理: 利用python的PIL自带的灰度图像转换函数,首先将彩色图 ...
- word2vec 中的数学原理二 预备知识 霍夫曼树
主要参考: word2vec 中的数学原理详解 自己动手写 word2vec 编码的话,根是不记录在编码中的 这一篇主要讲的就是霍夫曼树(最优二叉树)和编码. ...
- 霍夫曼编码(Huffman Coding)
霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种. 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符 ...
- 采用霍夫曼编码(Huffman)画出字符串各字符编码的过程并求出各字符编码 --多媒体技术与应用
题目:有一个字符串:cabcedeacacdeddaaaba,问题: (1)采用霍夫曼编码画出编码的过程,并写出各字符的编码 (2)根据求得的编码,求得各编码需要的总位数 (3)求出整个字符串总编码长 ...
- word2vec中关于霍夫曼树的
再谈word2vec 标签: word2vec自然语言处理NLP深度学习语言模型 2014-05-28 17:17 16937人阅读 评论(7) 收藏 举报 分类: Felven在职场(86) ...
- 霍夫曼编码(Huffman)
题目:有一个字符串:cabcedeacacdeddaaaba,问题: (1)采用霍夫曼编码画出编码的过程,并写出各字符的编码 (2)根据求得的编码,求得各编码需要的总位数 (3)求出整个字符串总编码长 ...
随机推荐
- Visual Studio 2012 编译错误【error C4996: 'scanf': This function or variable may be unsafe. 】的解决方案(转载)
转载:http://www.th7.cn/Program/c/201303/127343.shtml 原因是Visual C++ 2012 使用了更加安全的 run-time library rout ...
- 本地连接VM virtualBox ubuntu16.04 中的Mysql数据库
1.打开mysql配置文件vim /etc/mysql/mysql.conf.d/mysqld.cnf 将bind-address = 127.0.0.1注销 2.重启ubuntu数据库 3. ...
- 浅入浅出JS中的eval及json
声明: 首先声明一下,本人是JS新手,所以不敢说深入,只是把最近对eval的学习经验拿出来跟大家分享,如果您是高手可略去不看. 适合读者: 对JS中的eval一知半解,不知eval是如何把字符串转换为 ...
- dp入门 专题记录 2017-7-26
POJ3176-Cow Bowling 题目大意:现有n行数,以金字塔的形式排列,即第一行一个数字,第二行2个数字,依次类推,现在需要找一条从第一层到第n层的路线,使得该路线上的所有点的权值和最大 思 ...
- 项目梳理7——Nuget包管理
1.添加Nuget源 nuget包管理.生成自己的nuget包.向 NuGet 添加更多程序包源 nuget的所有使用介绍 打包示例 .nuspec文件声明的是对应NuGet包的以下内容: 包更新命令 ...
- 学习mybatis-3 step by step 篇二
Mapper XML 文件 基本的*Mapper.xml文件配置就不熬述了具体可参考: http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html 1.sq ...
- Linux command line exercises for NGS data processing
by Umer Zeeshan Ijaz The purpose of this tutorial is to introduce students to the frequently used to ...
- codeforces804D Expected diameter of a tree
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- dos与unix系统的格式转化
unix 只用\n作为行结束符,而在 dos中是以\r和\n作为行结束符, 如果一个文件是在unix系统下创建,然后想在dos下使用,就要用unix2dos,如 unix2dos file 如果一个文 ...
- 用NotePad++如何实现大小写转换
1.小写转换大写 Ctrl + Shift + U 2.大写转换小写 Ctrl + U