Codeforces 818F Level Generation(三分)

来源:互联网 发布:java99乘法表数组编程 编辑:程序博客网 时间:2024/05/24 03:19

F. Level Generation
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Ivan is developing his own computer game. Now he tries to create some levels for his game. But firstly for each level he needs to draw a graph representing the structure of the level.

Ivan decided that there should be exactly ni vertices in the graph representing level i, and the edges have to be bidirectional. When constructing the graph, Ivan is interested in special edges called bridges. An edge between two vertices u and v is called a bridge if this edge belongs to every path between u and v (and these vertices will belong to different connected components if we delete this edge). For each level Ivan wants to construct a graph where at least half of the edges are bridges. He also wants to maximize the number of edges in each constructed graph.

So the task Ivan gave you is: given q numbers n1, n2, …, nq, for each i tell the maximum number of edges in a graph with ni vertices, if at least half of the edges are bridges. Note that the graphs cannot contain multiple edges or self-loops.

Input
The first line of input file contains a positive integer q (1 ≤ q ≤ 100 000) — the number of graphs Ivan needs to construct.

Then q lines follow, i-th line contains one positive integer ni (1 ≤ ni ≤ 2·109) — the number of vertices in i-th graph.

Note that in hacks you have to use q = 1.

Output
Output q numbers, i-th of them must be equal to the maximum number of edges in i-th graph.

Example
input
3
3
4
6
output
2
3
6
Note
In the first example it is possible to construct these graphs:

1 - 2, 1 - 3;
1 - 2, 1 - 3, 2 - 4;
1 - 2, 1 - 3, 2 - 3, 1 - 4, 2 - 5, 3 - 6.

题目大意:

  告诉你结点数,让你构造一张图,其中桥至少要占边数的一半,问最多能够有多少条边。

解题思路:

  我们可以先取x个点形成一个完全子图,剩下的连成一条链,并和这个子图连接上,这样链中的边全部都是桥。完全子图中有x(x1)2条边,链上有Vx条边。由于题目要求桥至少要占边数的一半,所以完全子图中保留min(x(x1)2,Vx)条边,最终对于取x个点形成完全子图的情况最多有f(x)=min(x(x1)2,Vx)+Vx条边。很明显f(x)是凸函数,我们可以三分得到答案。

AC代码:

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <vector>#include <queue>#include <stack>#include <map>using namespace std;#define INF 0x3f3f3f3f#define LL long long#define fi first#define se second#define mem(a,b) memset((a),(b),sizeof(a))#define sqr(x) ((x)*(x))LL N;inline LL judge(const LL &x){    return min(N-x, x*(x-1)/2)+N-x;}int main(){    int T_T;    scanf("%d", &T_T);    while(T_T--)    {        scanf("%lld", &N);        LL l=1, r=N;        while(r-l>2)        {            LL mid=(l+r)/2;            LL midmid=(mid+r)/2;            if(judge(midmid)>judge(mid))                l=mid;            else r=midmid;        }        printf("%lld\n", max(judge(l), max(judge(l+1), judge(r))));    }    return 0;}