2014-2015 ACM-ICPC, Asia Xian Regional Contest C
2016-09-07 22:09
423 查看
Problem C. The Problem Needs 3D Arrays
Description
A permutation is a sequence of integers
p1, p2,
. . . , pn, consisting of
n distinct positive
integers and each of them does not exceed
n. Assume that
r(S)
of sequence
S denotes the
number of inversions in sequence
S (if
i < j and
Si > Sj, then the
pair of (i, j)
is called an
inversion of
S),
l(S)
of sequence
S denotes the length of sequence
S. Given a permutation
P
of length
n, it’s your task to find a subsequence
S of
P with maximum
r l( (S S) ).
A subsequence
of P is a sequence (pi1,
pi2, . . . , pit)
which satisfies that 0
< i1
< i2
< . . . < it ≤
n.
Input
The first line of the input gives the number of test cases, T. T test cases follow.
For each test case, the first line contains an integer
n (1
≤ n
≤ 100), the length of
the permutation
P. The second line contains
n integers
p1, p2,
. . . , pn, which represents the
permutation
P.
Output
For each test case, output one line containing “Case #x: y”, where x is the test case
number (starting from 1) and y is the maximum
r l( (S S) ).
Your answer will be considered correct if it is within an absolute error of
10−6
of the correct
answer.
Samples
Sample Input Sample Output
15
3 4 2 5 1
Case
#1: 1.250000000000
题意:
有一个长度为n的序列,现要从中选择一个子序列s,
定义r(s):子序列的逆序对数
l(s):子序列的长度
要求r(s)/l(s)的最大值
solution:
二分ans,判断r(s)/l(s)
>= ans
若不等式成立则答案不小于ans
变形得r(s)
- l(s)*ans >= 0
这个东西意味着我们要舍去一些逆序对,同时减去一个东西
那最优的方案就是让花费的代价最小
联系到最小割,利用最大权闭合子图的方法
源点向每个位置连边,权值为ans
若两点(i,j)构成逆序对,构建一个辅助点k,i->k容量为INF,j->k容量为INF,k->汇点容量为1
判断初始逆序对
- 最大流是否大于零
正确性就不赘述了
Description
A permutation is a sequence of integers
p1, p2,
. . . , pn, consisting of
n distinct positive
integers and each of them does not exceed
n. Assume that
r(S)
of sequence
S denotes the
number of inversions in sequence
S (if
i < j and
Si > Sj, then the
pair of (i, j)
is called an
inversion of
S),
l(S)
of sequence
S denotes the length of sequence
S. Given a permutation
P
of length
n, it’s your task to find a subsequence
S of
P with maximum
r l( (S S) ).
A subsequence
of P is a sequence (pi1,
pi2, . . . , pit)
which satisfies that 0
< i1
< i2
< . . . < it ≤
n.
Input
The first line of the input gives the number of test cases, T. T test cases follow.
For each test case, the first line contains an integer
n (1
≤ n
≤ 100), the length of
the permutation
P. The second line contains
n integers
p1, p2,
. . . , pn, which represents the
permutation
P.
Output
For each test case, output one line containing “Case #x: y”, where x is the test case
number (starting from 1) and y is the maximum
r l( (S S) ).
Your answer will be considered correct if it is within an absolute error of
10−6
of the correct
answer.
Samples
Sample Input Sample Output
15
3 4 2 5 1
Case
#1: 1.250000000000
题意:
有一个长度为n的序列,现要从中选择一个子序列s,
定义r(s):子序列的逆序对数
l(s):子序列的长度
要求r(s)/l(s)的最大值
solution:
二分ans,判断r(s)/l(s)
>= ans
若不等式成立则答案不小于ans
变形得r(s)
- l(s)*ans >= 0
这个东西意味着我们要舍去一些逆序对,同时减去一个东西
那最优的方案就是让花费的代价最小
联系到最小割,利用最大权闭合子图的方法
源点向每个位置连边,权值为ans
若两点(i,j)构成逆序对,构建一个辅助点k,i->k容量为INF,j->k容量为INF,k->汇点容量为1
判断初始逆序对
- 最大流是否大于零
正确性就不赘述了
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> using namespace std; const int maxn = 1E4 + 1E3 + 10; const int maxm = 1E5 + 10; const int INF = ~0U>>1; typedef double DB; const DB eps = 1E-12; struct E{ int to; DB cap,flow; E(){} E(int to,DB cap,DB flow): to(to),cap(cap),flow(flow){} }edgs[maxm]; int n,m,s,t,cnt,T,tot,Cnt,a[111],L[maxn],vis[maxn],cur[maxn]; DB ori; vector <int> v[maxn]; queue <int> Q; void Add(int x,int y,DB cap) { v[x].push_back(cnt); edgs[cnt++] = E(y,cap,0); v[y].push_back(cnt); edgs[cnt++] = E(x,0,0); } bool BFS() { vis[s] = ++Cnt; L[s] = 1; Q.push(s); while (!Q.empty()) { int k = Q.front(); Q.pop(); for (int i = 0; i < v[k].size(); i++) { E e = edgs[v[k][i]]; if (e.cap - e.flow <= eps) continue; if (vis[e.to] == Cnt) continue; vis[e.to] = Cnt; L[e.to] = L[k] + 1; Q.push(e.to); } } return vis[t] == Cnt; } DB Dicnic(int x,DB a) { if (x == t) return a; DB flow = 0; for (int &i = cur[x]; i < v[x].size(); i++) { E &e = edgs[v[x][i]]; if (e.cap - e.flow <= eps) continue; if (L[e.to] != L[x] + 1) continue; DB f = Dicnic(e.to,min(a,e.cap - e.flow)); if (f < eps) continue; e.flow += f; edgs[v[x][i]^1].flow -= f; a -= f; flow += f; if (a <= eps) return flow; } if (flow <= eps) L[x] = -1; return flow; } bool Judge(DB now) { ori = 0; cnt = 0; s = 0; t = tot = n + 1; for (int i = 1; i < n; i++) for (int j = i + 1; j <= n; j++) if (a[i] > a[j]) { ++tot; Add(i,tot,INF); Add(j,tot,INF); Add(tot,t,1); ori += 1.00; } for (int i = 1; i <= n; i++) Add(s,i,now); DB MaxFlow = 0; while (BFS()) { for (int i = 0; i <= tot; i++) cur[i] = 0; MaxFlow += Dicnic(s,INF); } for (int i = 0; i <= tot; i++) v[i].clear(); return ori - MaxFlow >= eps; } int main() { #ifdef DMC freopen("DMC.txt","r",stdin); #endif cin >> T; for (int I = 1; I <= T; I++) { scanf("%d",&n); for (int i = 1; i <= n; i++) scanf("%d",&a[i]); DB L = 0,R = n + 1; for (int i = 0; i < 50; i++) { DB mid = (L + R) / 2.00; if (Judge(mid)) L = mid; else R = mid; } printf("Case #%d: %.12lf\n",I,L); } return 0; }
相关文章推荐
- Android Service与Activity之间通信的几种方式
- Spring Boot + Elasticsearch
- Oracle系列:(15)集合查询
- Linux Jboss下logback日志框架的输出日志只保留10天的问题
- 给定二叉树的先序遍历中序遍历,求后序遍历
- ArcMap设置数据显示小数整数位的0
- POJ 1002 487-3279 水题字符串
- 19. Yii 2.0 数据分页
- 给定二叉树的先序遍历中序遍历,求后序遍历
- 虚拟机VirtualBox 5.1.0|VBOX
- Fast R-CNN论文详解
- java 使用RandomAccessFile类基于指针方式读写文件
- Sublime Text 如何连接 FTP/SFTP
- Qt QThread 爬坑之旅(一)
- 【Windows】记下几个比较常用的cmd操作命令
- 微信 公众平台开发者文档
- Activity有多个启动图标
- Linux Linux程序练习七
- linux下使用openssl对socket通信加密
- Eclipse Mars.2 JSP文件字体大小设置