摘要:
BZOJ_2274 这个题目不难得到dp的递推方程,f[i]=sum{f[j](A[i]-A[j]>=0)},但是如果裸着做显然是O(N^2)的复杂度,但如果我们把每次计算的f[i]依A[i]的值的大小存到对应的位置时,每次就可以O(logN)求得sum{f[j](A[i]-A[j]>=0)}了。#include<stdio.h>#include<string.h>#include<algorithm>#define MAXD 100010#define MOD 1000000009int N, S, a[MAXD], A[MAXD], sum[ 阅读全文
摘要:
BZOJ_2197 如果子树中有某个节点不符合要求,即便根再怎么符合要求都是没有任何意义的,因此要优先安排好子树中节点使其符合要求,再考虑根节点。对于任何一棵子树来讲,如果所有孩子选择的点的总和仍然不足根的C值的话,那么就还要在孩子中选出一些节点,而且如果要选那么必然应该选T最小的点。#include<stdio.h>#include<string.h>#include<algorithm>#define MAXD 100010#define MAXM 100010typedef long long LL;int N, first[MAXD], e, nex 阅读全文
摘要:
BZOJ_2442 这个题目可以用f[i]表示递推到第i个点时得到的最优解。不妨设A[]表示前缀和,那么当前有两种决策,要么不选当前这个点,要么一并向前选择若干个点,这样可以得到状态转移方程f[i]=max{f[j]+A[i]-A[j+1](i-K-1<=j<=i-2),f[i-1]}。 如果裸着做的话是O(N^2)的,但是对状态转移方程中f[j]+A[i]-A[j+1]变形之后就会得到f[j]-A[j+1]+A[i],这样如果我们用单调队列维护f[j]-A[j+1]的最大值就可以做到O(1)决策了。#include<stdio.h>#include<string 阅读全文
摘要:
POJ_3666 由于递增和递减是类似的,下面不妨只讨论变成递增序列的情况。 我们可以用f[i][j]表示递推到第i个数时,将第i个数变成<=j且满足序列是非减的所需要的最小的代价。由于j的范围较大,可以先离散化,不妨设最后一共有S个不同的数,那么我们要计算的就是f[N][S]。 可以得到f[i][j]=std::min(f[i-1][j]+abs(...),f[i][j-1]),式子中的...表示省略了一部分内容。如果还想优化空间的话,用滚动数组实现即可。#include<stdio.h>#include<string.h>#include<algorit 阅读全文
摘要:
POJ_3670 由于递增和递减是类似的,下面不妨只讨论变成递增序列的情况。 由于Di只有三个数,所以可以考虑将序列分割成三部分,第一部分全部变成1,第二部分全部变成2,第三部分全部变成3。然后我们枚举3开始的位置,这时一共有若干决策,要么前面的全部是1,要么前面有一段2,然后再前面有一段1或者没有,如果每种决策都考察一遍的话整体复杂度就要O(N^2)了,因此考虑优化一下。记当前的位置为i,1的最后一个位置为j,not1[k]表示k以及k之前不是1的数量,not2[k]表示k以及k之前不是2的数量,not3[k]表示k以及k之后不是3的数量,那么我们把决策表示成not2[i]+(not1[j] 阅读全文
摘要:
POJ_3669 广搜一下即可。#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>#define MAXD 310#define INF 0x3f3f3f3fint N, danger[MAXD][MAXD], dis[MAXD][MAXD];int dx[] = {-1, 1, 0, 0, 0}, dy[] = {0, 0, -1, 1, 0};int inside(int x, int y){ return x >= 0 && y & 阅读全文
摘要:
POJ_3668 可以先将所有的直线求出来,然后按斜率排个序,之后顺序扫描一遍就可以统计出结果了。#include<stdio.h>#include<string.h>#include<algorithm>#define MAXD 210struct Point{ int x, y; bool operator < (const Point &t) const { if(x == t.x) return y < t.y; return x < t.x; }}p[MAXD];struct Vector{ int x, y; bool. 阅读全文
摘要:
POJ_1274 直接用匈牙利算法求二分图的最大匹配即可。#include<stdio.h>#include<string.h>#define MAXD 210int N, M, g[MAXD][MAXD], visy[MAXD], yM[MAXD];void init(){ int i, j, n, x; memset(g, 0, sizeof(g)); for(i = 1; i <= N; i ++) { scanf("%d", &n); for(j = 0; j < n; j ++) { scanf(... 阅读全文
摘要:
UVALive_4981 首先判断一个括号序列是否合法,可以用一个栈来实现。 为了让字典序只大那么一点点,必然保留的前缀长度越长越好,因此可以枚举保留的前缀的长度,接着,除去前缀的下一个字符应该大得越少越好,这一点也可以枚举,如果此时依然合法的话就要看剩下的字符的数量能否让栈中的左括号全部出栈,如果不行的话显然也是不合法的。如果还有多余的字符呢?由于我们已经让前缀的下一个字符比原来的这个位置的字符大了,那么后面的字符的字典序就应该越小越好,所以我们应该在紧邻的位置补类似ae、aaee、aaaeee这样的东西,至于补多长就要依剩余的字符的数量而定了。#include<stdio.h> 阅读全文
摘要:
SPOJ_1825 树的分治的题目,详细的算法可以参考09年漆子超的论文《分治算法在树的路径问题中的应用》。#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>#define MAXD 200010#define MAXM 400010#define INF 0x3f3f3f3fint N, K, M, first[MAXD], e, next[MAXM], v[MAXM], w[MAXM], col[MAXD];int q[MAXD], size[MAXD] 阅读全文