随笔分类 - ACM题解
摘要:模型:求n个城市的最短hamilton回路,n<=15。分析:看到n<=15这样的条件容易想到状态压缩DP。hamilton回路其实就是n个城市的一个圆排列,任选一个起点最后的结果都一样,我们不妨设结点0为起点,状态设计也就不难了。状态设计:d[s][last],表示从结点0出发,已经走过的结点构成状态s,最后走的结点为last;状态转移:d[s][last]=MIN(d[ns][k]+g[k][last]),ns为s中去掉last那一位,k为ns中是1的位(不能是起点0);边界:当s中只有2位是1的时候,说明从0结点出发,到达last,所以直接返回g[0][last]。结果:an
阅读全文
摘要:题意:给一个正整数序列,记为a1,a2,……an,现需找i,j,使得i<j,并且ai与aj之间的数均比ai大,均比aj小,求符合上述条件的i与j,使得j-i的最大。分析:易知序列中的最小值比其他所有数都小,最大值比其他所有数都大,所以可以现找到最小的数与最大的数的位置,记为i,j,若i<j,则区间[i,j]内符合上述条件的最值就是j-i,然后递归求解左右区间[1,i-1],[j+1,n],若i>j,则将区间分为三段递归求解,[1,j],[j+1,i-1],[i,n]。递归边界为区间左端点>=区间右端点时返回-1。每次求区间的最大与最小值的位置可以用线段树解决。View
阅读全文
摘要:题意:给一棵含n个结点的树,现要查询从a到b的路径中是否包含c,共q次查询。1=<n,q<=100000分析:由于在树中从一个结点走到另一个结点的路径是唯一的,其实说的这条路径就是最短路径,然后问题转化为判断一个点是否为在一条最短路径上,此时就不难想到这个这个判断条件d(a,c)+d(c,b)=d(a,b),问题就转化为查询树中2个结点之间的距离,这个可以用LCA来做(参考上一篇),考虑到n和q都比较大,所以用离线LCA.View Code #include <stdio.h>#include <string.h>#define N 100010#defin
阅读全文
摘要:题意:给一棵带权重的树,共有k个查询,每次查询树中2个结点的距离。结点数n最大为40000,k最大10000分析:首先我们将无根树转为有根树,可以在O(n)时间内得到每个结点到根结点的距离。由于在树中从一个结点走到另一个结点的路径是唯一的,所以a到b的路径一定经过lca(a,b),设lca(a,b)=c。此时不难发现d(a,b)=d(a,root)+d(b,root)-2*d(c,root)。先在问题就是如何快速求LCA,由于结点数目比较大,查询比较多,所以用在线算法会超时。这里用的是tarjan离线算法,时间复杂度为O(n+k)。View Code #include <stdio.h&
阅读全文
摘要:模型:给定一个整数矩阵,查询某个子矩阵中的最大数与最小数之差。N最大为250,查询数K最大为100000我的做法:用线段树求出要查询的子矩阵每一行的最大与最小,然后在列方向上统计子矩阵的最大与最小。有点暴力,跑了800+ms。View Code #include <stdio.h>#include <string.h>#define N 255#define MAX(a,b) ((a)>(b)?(a):(b))#define MIN(a,b) ((a)<(b)?(a):(b))int n,b,k,D;int max[N][4*N];int min[N][4*
阅读全文
摘要:题目大意:给你一个含n个整数的不下降序列,现需查询某个区间内出现次数最多的数,对于每次查询输出出现最多的次数即可。分析:由于序列是有序的,所以一个数如果在序列中出现多次,那么一定是连续出现的,这样的话就可以把问题转化为区间染色问题,查询的是某个区间中最长的同色区间的长度。区间保存的关键信息有,区间内的某数出现的最大次数,区间最左边的数及其在该区间内出现的次数,区间最右边的数及其在该区间内出现的次数。保存左右两边的信息为为了更新父结点,因为父结点的最大answer可能由左儿子和右儿子合并得到。这题我一开始用堆实现的线段树,发现了很多问题,用堆实现的线段树中有很多没有用到的空间,处理不好会造成结果
阅读全文
摘要:定义windy数:相邻数字的差至少是2的数,例如10不是windy数,而13是windy数。求给定区间中有多少windy数。区间端点范围为 [1, 2000000000]dfs写法#include <stdio.h>#include <string.h>#define N 10int dp[N][N],digit[N];int dfs(int pos,int last,int z,int f){ if(pos==-1) return 1; if(z&&!f&&dp[pos][last]!=-1) return dp[pos][last];
阅读全文
摘要:题意:求n到m中有多少个数不含“4”和“62”View Code #include <stdio.h>#include <string.h>#define LEN 10char a[LEN],b[LEN];int n,m;int dp[LEN][3][2];int nextstate(int cur,int in){ if(cur==2 || cur==1&&in==2 || in==4) return 2; return in==6;}int nextflag(int cur,int in,int max){ if(cur==1 &&
阅读全文
摘要:题目大意:求1到n中有多少个数含“49”第一次接触按位DP,参考了别人的题解。第一个代码运行速度快些(31ms),但状态的转移的分析比较麻烦,第二个代码要慢些(125ms),但code比较方便。View Code #include <stdio.h>#include <string.h>#define LEN 22typedef __int64 LL;char s[LEN];LL dp[LEN][3][2];int next(int cur,int in){ if(cur==2 || cur==1&&in==9) return 2; return in=
阅读全文
摘要:题目大意:给一个n*m的方格地图,每个方格中有一个字符,'.'草地,'*'泥巴地,给你一些宽为1方格大小的板子,长度不限,问最少需要多少板子才能盖住所有的泥巴地,但是不能盖住草地,板子允许相互覆盖。分析:扫描行,将连通的泥巴地看成一个结点,这样得到二分图的X部,按同样的方法扫描列得到二分图的Y部,有公共方格的结点之间连边。View Code #include <stdio.h>#include <string.h>#define N 51#define M 51char map[N][M];bool g[N*M][N*M];int n,m
阅读全文
摘要:题意:给定n个单词(均为大写字母)和一个文本(均为可见字符),求每个单词在文本中出现的次数。单词数不超过1000,长度不超过50,文本长度不超过2000000分析:AC自动机基础题。一个小的优化:由于单词均为大写字母,所以建字典树时第二维大小可以只开26,这样可以节约时间和空间,在扫描文本时(均为可见字符),碰到非大写字母时,直接将指针指向根结点,继续扫描下一个字符即可。View Code #include <stdio.h>#include <string.h>#include <queue>using namespace std;#define LEN
阅读全文
摘要:题意:给n个单词和一个文本,求有多少个单词出现在文本中。据说这题是AC自动机的模版题。这题也是我写的第一个AC自动机的题。View Code #include <stdio.h>#include <string.h>#include <queue>using namespace std;#define LEN 55#define N 10010int n,node;int next[N*LEN][26];int cnt[N*LEN];int fail[N*LEN];void init(){ memset(next[0],0,sizeof(next[0]));
阅读全文
摘要:题意:给定一个n*n的棋盘,棋盘中的'X’代表障碍物,'.'代表空地,问在空地上最多放多少车,使得它们不会互相攻击。分析:由于n比较小,应该可以直接暴力,这里用的二分匹配的方法。建图:先扫描行,连通的格子看成一个结点,这样可以得到二分图的X部,再同样扫描列,得到Y部,有公共方格的结点连边,然后求最大匹配就是结果。正确性分析:扫描行得到的结点之间不可能有公共方格,所以X部的结点内部没有连边,同理Y部的结点内部结点没有连边,所以建立的图是二部图。每个结点内最多只能放一个车,有公共方格的结点最多只能选取其中一个放车,这样就得到一个最大匹配的模型。View Code #incl
阅读全文
摘要:Description一个每块地板标记着0~9某个数字的迷宫,其中标记1的地板不可以走,标记2~9的地板可以不花时间地跳到任意相同数字的位置,也可以和标记0的地板一样向前后左右任意方向花1个单位时间移动1的距离。给出起点和终点,求起点到终点的最短时间。Input每组数据第一行一个n,表示尺寸,2 <= n <= 100。接下来n行每行n个0~9的字符,或S表示起点,E表示终点,S和E的运动规则与0相同。整个地图只有一个S和一个E。Output每组数据输出一个数,占一行,表示起点到终点可以花费的最短时间。如果无法到达重点,输出"Oh No!"Sample Inpu
阅读全文
摘要:Description 现在有一个N个整数组成的序列,这N个整数的标号分别为1, 2, ..., N,对这个序列一共进行两类操作: ① 1 x y:表示将第x个和第y个(包括x、y)整数之间的所有整数的二进制的最低位的1变为0,如果某个整数的值为0,则不对这个整数做任何改变。 ② 2 x y :表示你需要回答第x个和第y个(包括x、y)整数之间的所有整数异或的结果。Input 输入包含多组测试数据。 对于每组测试数据,第一行包含两个正整数N(2<=N<=10^4)、M(1<=M<=10^5),表示这个序列一共有N个整 数,你需要处理M次操作。接下来一行一共有N个不超过2
阅读全文
摘要:Description 在另一个平行宇宙中,有一个神奇的国度名叫天朝。天朝一共有N个城市(标号分别为1, 2, …, N),M条道路,为了方便交通管制,天朝的M条道路都是单行道。 不久前天朝大选,小Q当选了天朝的总统。小Q家住在城市1,但天朝的办公地点在城市N,于是为了便于工作,小Q决定举家从城市1搬迁到城市N去居住。然而小Q惊奇的发现,现在并不存在从城市1出发到城市N路线。 但这点难题是无法阻挡天朝总统的,小Q决定行使总统的权利下令更改一些道路的通行方向,使得至少存在一条从城市1出发到城市N的路线,但为了节省时间和资源,他希望更改通行方向的道路尽可能少,你能帮帮小Q吗?Input 输...
阅读全文
摘要:Description有很多个棱长为1的正方体货物整齐地堆在一堆。不过有一些是悬空的, 大概是粘上去的吧。。。给出这些货物的相邻关系,求最小的长方体(或正方体)能装下这些货物的集装箱的体积,(集装箱棱长方向与这些正方体三个棱方向平行)。Input每组数据第一行一个n,表示有n个货物。1 <= n <= 1000接下来n行每行6个数,第i行表示以棱方向为轴的x轴正负、y轴正负、z轴正负方向与第i个货物相邻的货物编号(i为1~n),0表示无该位置信息。Output如果描述出现矛盾或者无法确定货物是堆在一起的,输出"What?",否则输出集装箱体积。Sample In
阅读全文
摘要:DescriptionHarmony is indispensible in our daily life and no one can live without it----may be Facer is the only exception. One day it is rumored that repeat painting will create harmony and then hundreds of people started their endless drawing. Their paintings were based on a small template and a s
阅读全文
摘要:题目大意:给一个字典和一些单词,根据字典翻译这些单词,若字典中没有就输出"eh"。View Code #include <stdio.h>#include <map>#include <string>using namespace std;#define N 11map<string,string>dic;int main(){ char a[N],b[N]; char c; scanf("%s%c",a,&c); while(c==' ') { scanf("%s&quo
阅读全文
摘要:跟上一题差不多,就是输入的处理比较麻烦。View Code #include <stdio.h>#include <string.h>#include <queue>using namespace std;#define MIN(a,b) ((a)<(b)?(a):(b))#define N 105int n,ns,nt,m;int g[N][N];int pre[N];void EK(int s,int t){ int u,v,maxflow=0; while(1) { queue<int>q; memset(pre,-1,sizeof(
阅读全文

浙公网安备 33010602011771号