不是有很多可以说的,记住不能边算边取min

Code

 #include<iostream>
#include<fstream>
#include<sstream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#include<set>
using namespace std;
typedef bool boolean;
#define INF 0xfffffff
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b) ifstream fin("word.in");
ofstream fout("word.out"); int n;
int c;
char str[]; inline void init() {
fin >> str;
n = strlen(str);
} int counter[];
inline void solve() {
int minv = , maxv = ;
memset(counter, , sizeof(counter));
for(int i = , ch; i < n; i++) {
ch = (int) (str[i] - 'a');
counter[ch]++;
}
for(int i = ; i < ; i++) {
if(counter[i] != ) {
smin(minv, counter[i]);
smax(maxv, counter[i]);
}
}
c = maxv - minv;
if(c < ) {
fout << "No Answer" << endl;
fout << << endl;
} else if(c == || c == ) {
fout << "Lucky Word" << endl;
fout << c << endl;
} else {
int limit = (int)sqrt(c + 0.5);
for(int i = ; i <= limit; i++) {
if(c % i == ) {
fout << "No Answer" << endl;
fout << << endl;
return;
}
}
fout << "Lucky Word" << endl;
fout << c << endl;
}
} int main() {
init();
solve();
fin.close();
fout.close();
return ;
}


  记下每个数字所需的火柴数,然后去搜索吧,或者找出上界,枚举两个加数,再判断是否可行。

Code

 #include<iostream>
#include<fstream>
#include<sstream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#include<set>
using namespace std;
typedef bool boolean;
#define INF 0xfffffff
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b) ifstream fin("matches.in");
ofstream fout("matches.out"); int n; inline void init() {
fin >> n;
n -= ;
} const int cost[] = {, , , , , , , , , }; int result = ;
int buf[]; int getInt(int from, int end) {
if(buf[from] == && end - from > ) return -;
if(buf[from] == ) return ;
int ret = ;
for(int i = from; i < end; i++) {
ret *= ;
ret += buf[i];
}
return ret;
} int check(int top) {
int res = ;
if(top < ) return ;
// if(buf[0] == 0 && buf[1] == 0) return (buf[2] == 0 && top == 3) ? (1) : (0);
for(int i = ; i < top - ; i++) {
for(int j = i + ; j < top; j++) {
int a = getInt(, i);
int b = getInt(i, j);
int c = getInt(j, top);
if(a + b == c) res++;//, fout << a << "+" << b << "=" << c << endl;;
}
}
return res;
} void dfs(int pos, int used) {
if(used == n) {
result += check(pos);
return;
}
for(int i = ; i <= ; i++) {
if(used + cost[i] <= n) {
buf[pos] = i;
dfs(pos + , used + cost[i]);
}
}
} inline void solve() {
dfs(, );
fout << result;
fin.close();
fout.close();
} int main() {
init();
solve();
return ;
}


  从下面传上来,等于从上面传下去,原问题就等于从左上角找两条互不相交的路径,简单地是写个dp,f[x0][y0][x1][y1]或者f[dis][x0][x1],然而我先想到的是网络流,将每个点拆成2个点(除去左上角的和右下角那个),中间连一条容量为1,费用为0的有向边。其他边按照题目意思来建。也是容量为1,费用为起点的点权。然后求左上角到右下角流量为2的最大费用流。(noip用网络流?)

Code

 #include<iostream>
#include<fstream>
#include<sstream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#include<set>
using namespace std;
typedef bool boolean;
#define inf 0xfffffff
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b) typedef class Edge {
public:
int end;
int next;
int flow;
int cap;
int cost;
Edge(const int end = , const int next = , const int flow = , const int cap = , const int cost = ):end(end), next(next), flow(flow), cap(cap), cost(cost) { }
}Edge; typedef class MapManager {
public:
int ce;
int* h;
Edge* edge;
MapManager():ce(), h(NULL), edge(NULL) { }
MapManager(int points, int limit):ce() {
h = new int[(const int)(points + )];
edge = new Edge[(const int)(limit + )];
memset(h, , sizeof(int) * (points + ));
}
inline void addEdge(int from, int end, int flow, int cap, int cost) {
edge[++ce] = Edge(end, h[from], flow, cap, cost);
h[from] = ce;
}
inline void addDoubleEdge(int from, int end, int cap, int cost) {
addEdge(from, end, , cap, cost);
addEdge(end, from, cap, cap, -cost);
}
Edge& operator [](int pos) {
return edge[pos];
}
int reverse(int pos) {
return (pos & ) ? (pos + ) : (pos - );
}
}MapManager;
#define m_begin(g, i) (g).h[(i)] ifstream fin("message.in");
ofstream fout("message.out"); int n, m;
MapManager g;
int l; inline int pti(int x, int y) { return x * n + y; }
inline void init() {
fin >> m >> n;
g = MapManager( * m * n, * m * n);
l = m * n;
for(int i = , a; i < m; i++) {
for(int j = ; j < n; j++) {
fin >> a;
g.addDoubleEdge(pti(i, j), pti(i, j) + l, , );
if(i < m - ) g.addDoubleEdge(pti(i, j) + l, pti(i + , j), , a);
if(j < n - ) g.addDoubleEdge(pti(i, j) + l, pti(i, j + ), , a);
}
}
} int* dis;
boolean *visited;
int* last;
int* lase;
int* mflow;
int cost;
queue<int> que;
boolean spfa(int s, int t) {
memset(dis, 0xf0, sizeof(int) * ( * l + ));
memset(visited, false, sizeof(boolean) * ( * l + ));
dis[s] = last[s] = lase[s] = ;
que.push(s);
mflow[s] = inf;
visited[s] = true;
while(!que.empty()) {
int e = que.front();
que.pop();
visited[e] = false;
for(int i = m_begin(g, e); i != ; i = g[i].next) {
int& eu = g[i].end;
if(dis[e] + g[i].cost > dis[eu] && g[i].flow < g[i].cap) {
dis[eu] = dis[e] + g[i].cost;
last[eu] = e;
lase[eu] = i;
mflow[eu] = min(g[i].cap - g[i].flow, mflow[e]);
if(!visited[eu] && eu != t) {
que.push(eu);
visited[eu] = true;
}
}
}
}
if(!dis[t]) return false;
for(int i = t; i != s; i = last[i]) {
g[lase[i]].flow += mflow[t];
g[g.reverse(lase[i])].flow -= mflow[t];
cost += mflow[t] * g[lase[i]].cost;
}
return true;
} inline void solve() {
dis = new int[(const int)( * l + )];
visited = new boolean[(const int)( * l + )];
last = new int[(const int)( * l + )];
lase = new int[(const int)( * l + )];
mflow = new int[(const int)( * l + )];
cost = ;
spfa(l, l - );
spfa(l, l - );
fout << (cost);
} int main() {
init();
solve();
return ;
}


  首先来思考一下,对于单栈排序的要求。

  当且仅当存在这种情况不能排序:存在某个数j使得lis[j]大于它左边的某个位置i(i < j)的值lis[i],又大于右边某个位置k(k > j)的值lis[k],且lis[i]>lis[k]。可以随便举点例子2 3 1,2 4 3 1...这里就简单地说明一下,因为排序要是小的在前面,那么在k前面的都得先进栈,因为j在i后面,所以是lis[j]先被弹出栈,但lis[i]应该在它的前面,所以说这种情况不可以。

  当然考虑全面点还可以考虑一下其他情况

  现在回到双栈排序,对于不能用单栈排序完成的就扔到另一个栈完成...然后就会发现,这是一个二分图染色,对于有序数对(i,j)(i < j)满足上上面的情况,则就在i,j连一条边,因为i,j不能一个栈内排序,所以相连的点的颜色要不同。至于染色的方法可以参考noip2010第三题二分答案中判断的过程

  如果中间任何一个dfs的返回值为false,就说明无法用2个栈排序,按照题目意思输出0。

  最后就是按照题目意思,进行一个模拟:现在要把i弹出到输出队列,如果i不在双栈中,就把它及其它前面的元素放到stack[color[j]]中,然后再把它弹出来,否则就看看在哪个栈中,然后把它弹出来。然后题目要你输出什么就怎么输出。

  另外还有一个问题,建立二分图的时候如果暴力枚举i,j,k那么时间复杂度是O(n3),可以发现k被重复枚举了很多次,但是我们只需要知道对于数i,在位置j后是否存在比它小的数,于是就提前处以一个exist[i][j],这就可以把时间复杂度将为O(n2)。

  (PS:此题数据很水,dfs+暗黑剪枝比这种方法快得多)

Code

 #include<iostream>
#include<fstream>
#include<sstream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#include<set>
using namespace std;
typedef bool boolean;
#define INF 0xfffffff
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b) #define LOCAL
#ifndef LOCAL
#define fin cin
#define fout cout
#else
ifstream fin("twostack.in");
ofstream fout("twostack.out");
#endif template<typename T>class Matrix{
public:
T *p;
int lines;
int rows;
Matrix():p(NULL){ }
Matrix(int rows, int lines):lines(lines), rows(rows){
p = new T[(lines * rows)];
}
T* operator [](int pos){
return (p + pos * lines);
}
};
#define matset(m, i, s) memset((m).p, (i), (s) * (m).lines * (m).rows) ///map template starts
typedef class Edge{
public:
int end;
int next;
Edge(const int end = , const int next = ):end(end), next(next){}
}Edge;
typedef class MapManager{
public:
int ce;
int *h;
Edge *edge;
MapManager():h(NULL), edge(NULL){ }
MapManager(int points, int limit):ce(){
h = new int[(const int)(points + )];
edge = new Edge[(const int)(limit + )];
memset(h, , sizeof(int) * (points + ));
}
inline void addEdge(int from, int end){
edge[++ce] = Edge(end, h[from]);
h[from] = ce;
}
inline void addDoubleEdge(int from, int end){
addEdge(from, end);
addEdge(end, from);
}
Edge& operator [](int pos) {
return edge[pos];
}
inline void clear() {
delete[] h;
delete[] edge;
}
}MapManager;
#define m_begin(g, i) (g).h[(i)]
///map template ends int n;
int* lis;
Matrix<boolean> exist;
MapManager g; inline void init() {
fin >> n;
lis = new int[(const int)(n + )];
for(int i = ; i <= n; i++)
fin >> lis[i];
} inline void init_map() {
exist = Matrix<boolean>(n + , n + );
matset(exist, false, sizeof(boolean));
for(int i = ; i < n; i++) {
for(int j = n; j > i; j--) {
if(exist[i][j + ] || lis[j] < lis[i])
exist[i][j] = true;
}
} g = MapManager(n, * n * n);
for(int i = ; i < n; i++) {
for(int j = i + ; j <= n; j++) {
if(lis[j] > lis[i] && exist[i][j])
g.addDoubleEdge(i, j);
}
}
} int* color;
boolean dfs(int node, int val) {
if(color[node] != -) return color[node] == val;
else color[node] = val;
for(int i = m_begin(g, node); i != ; i = g[i].next) {
int& e = g[i].end;
if(!dfs(e, val ^ )) return false;
}
return true;
} inline void coloring() {
color = new int[(const int)(n + )];
memset(color, -, sizeof(int) * (n + ));
for(int i = ; i <= n; i++) {
if(color[i] == -)
if(!dfs(i, )) {
fout << << endl;
exit();
}
}
g.clear();
delete[] exist.p;
} int *s[];
int tops[] = {, };
int *status;
char its[] = {'a', 'c'};
inline void solve() {
for(int i = ; i < ; i++)
s[i] = new int[(const int)(n + )];
status = new int[(const int)(n + )];
memset(status, -, sizeof(int) * (n + ));
for(int i = , j = ; i <= n; i++) {
if(status[i] == -) {
while(j <= n && lis[j] != i) {
s[color[j]][tops[color[j]]++] = lis[j];
status[lis[j]] = color[j];
fout << its[color[j]] << " ";
j++;
}
status[lis[j]] = color[j];
fout << its[color[j]] << " " << (char) (its[color[j]] + ) << " ";
j++;
} else {
--tops[status[i]];
fout << (char) (its[status[i]] + ) << " ";
}
}
#ifdef LOCAL
fin.close();
fout.close();
#endif
} int main() {
init();
init_map();
coloring();
solve();
return ;
}

noip2008 真题练习 2017.2.25的更多相关文章

  1. 牛客网 PAT 算法历年真题 1010 : 月饼 (25)

    月饼 (25) 时间限制 1000 ms 内存限制 32768 KB 代码长度限制 100 KB 判断程序 Standard (来自 小小) 题目描述 月饼是中国人在中秋佳节时吃的一种传统食品,不同地 ...

  2. noip2010 真题练习 2017.2.18

    第一题比较简单,用exist数组判断是否在循环队列中,就可实现线性算法. Code #include<iostream> #include<cstdio> #include&l ...

  3. PAT乙级真题及训练题 1025. 反转链表 (25)

    PAT乙级真题及训练题 1025. 反转链表 (25) 感觉几个世纪没打代码了,真是坏习惯,调了两小时把反转链表调出来了,心情舒畅. 这道题的步骤 数据输入,数组纪录下一结点及储存值 创建链表并储存上 ...

  4. 美团点评2017校招笔试真题-算法工程师A

    美团点评2017校招笔试真题-算法工程师A 1.下面哪种STL容器的实现和其它三个不一样 A. set B. deque C. multimap D. map 正确答案: B STL的容器可以分为以下 ...

  5. 美团点评2017校招笔试真题-算法工程师B

    美团点评2017校招笔试真题-算法工程师B 1.以下关于经典的k-means聚类的说法哪个是错误的? A:k-means聚类算法是全局收敛的 B:k-means的聚类结果和初始聚类中心点的选取有关 C ...

  6. ACM-ICPC(10 / 10)——(完美世界2017秋招真题)

    今天学了莫比乌斯反演,竟然破天荒的自己推出来了一个题目!有关莫比乌斯反演的题解,和上次的01分数规划的题解明天再写吧~~~ 学长们都在刷面试题,我也去试了试,120分钟,写出6题要有一点熟练度才行.先 ...

  7. NOIP2010~2017部分真题总结

    NOIP2010~2017部分真题总结 2010 (吐槽)md这个时候的联赛还只有4题吗? 引水入城 只要发现对于有合法解的地图,每个蓄水厂贡献一段区间这个结论就很好做了 那么\(O(n^3)\)对每 ...

  8. 1054. 求平均值 (20)-PAT乙级真题

    今天刚刚到学校,2017年学习正式开始了,今天看到了浙大的<数据结构>这学期又要开课了,决定一定要跟着学习一遍:在大学生mooc网上学习:http://www.icourse163.org ...

  9. 蓝桥杯Java真题解析

    上个月参加蓝桥杯省赛拿了个省一,自从比赛完之后就一直没怎么写代码了,还有一个多月就要国赛了,从现在开始准备下国赛,但是我也不想学什么算法,而且我还在准备考研,所以就打算只做下历年的真题,争取国赛拿个国 ...

随机推荐

  1. CodeForces - 586D Phillip and Trains 搜索。vis 剪枝。

    http://codeforces.com/problemset/problem/586/D 题意:有一个3*n(n<100)的隧道.一个人在最左边,要走到最右边,每次他先向右移动一格,再上下移 ...

  2. python的几个注意事项

    ,==============坑======= 1.可变类型的值不要作为函数参数默认值,应该是不可变的对象,如None,True,False,数字或字符串 2.小心+= a = range(10) b ...

  3. django中admin的使用

    转载网址:https://www.cnblogs.com/wumingxiaoyao/p/6928297.html     Django自带的后台管理是Django明显特色之一,可以让我们快速便捷管理 ...

  4. js 调用声音提示

    function playSound() { var borswer = window.navigator.userAgent.toLowerCase(); if ( !!window.ActiveX ...

  5. /var/spool/postfix/maildrop 出现大量文件原因和解决办法

    今天发现服务器硬盘报警,出现空间不足的情况,后经查看发现是 /var/spool/postfix/maildrop 有大量文件,但服务器本身没有启动 postfix服务. 继续上网查资料,发现是cro ...

  6. HBase-0.95.1源码分析之split

    split操作执行的是将HBase中较大的Region分为两个.因为split比较耗时,因此split是在独立的线程中完成的,相关类是CompactSplitThread. 首先,CompactSpl ...

  7. 简述ASP.NET的页面运行机制

    在深入学习ASP.NET之前,首先需要先了解一下ASP.NET的页面运行机制: 浏览以下内容需要对ASP.NET管道有一定的了解,附上很不错的几个链接: 选择HttpHandler还是HttpModu ...

  8. Flask中'endpoint'(端点)的理解

    翻译整理自Stack Overflow:http://stackoverflow.com/questions/19261833/what-is-an-endpoint-in-flask 原文中用到了m ...

  9. javascript产生对象(不建议看)

    产生对象的方式:一.new+构造函数1.JavaScript的内置构造函数,如Date(),Function(),Array(),Object()2.自定义的构造函数二.对象字面量{}三.继承 用 v ...

  10. Keepalived+HAproxy实现高可用负载均衡

    总概:       Keepalived是一个类似于layer3, 4 & 5交换机制的软件,也就是我们平时说的第3层.第4层和第5层交换.Keepalived的作用是检测web服务器的状态, ...