DZY loves Physics, and he enjoys calculating density.
Almost everything has density, even a graph. We define the density of a non-directed graph (nodes and edges of the graph have some values) as follows:

Once DZY got a graph G, now he wants to find a connected induced subgraph G' of the graph, such that the density of G' is as large as possible.
An induced subgraph G'(V', E') of a graph G(V, E) is a graph that satisfies:
-
;
- edge
if and only if
, and edge
;
- the value of an edge in G' is the same as the value of the corresponding edge in G, so as the value of a node.
Help DZY to find the induced subgraph with maximum density. Note that the induced subgraph you choose must be connected.

The first line contains two space-separated integers n (1 ≤ n ≤ 500), . Integer n represents the number of nodes of the graph G, m represents the number of edges.
The second line contains n space-separated integers xi (1 ≤ xi ≤ 106), where xi represents the value of the i-th node. Consider the graph nodes are numbered from 1 to n.
Each of the next m lines contains three space-separated integers ai, bi, ci (1 ≤ ai < bi ≤ n; 1 ≤ ci ≤ 103), denoting an edge between node ai and bi with value ci. The graph won't contain multiple edges.
Output a real number denoting the answer, with an absolute or relative error of at most 10 - 9.
1 0 1
0.000000000000000
2 1 1 2 1 2 1
3.000000000000000
5 6 13 56 73 98 17 1 2 56 1 3 29 1 4 42 2 3 95 2 4 88 3 4 63
2.965517241379311
In the first sample, you can only choose an empty subgraph, or the subgraph containing only node 1.
In the second sample, choosing the whole graph is optimal.
题意:给定一个n个点m条边的无向图,每个点、每条边都有权值,找一个诱导子图是其点权和除以边权和值最大,输出最大值。
思路:只选一条边,对应的点权和除以边权中选最大值。下面给出大致的证明:
设最大值对应的点是u 、v, 即( w[ u ] +w[ v ] ) / w[ u , v ]最大,我们考虑在其两点基础上填边,不妨设v ' 与v相连,那么( w[ v ] + w[ v ' ] ) / w[ v, v ' ]<= ( w[ u ] +w[ v ] ) / w[ u , v ],
而v的点权只能用一次,那么必然 ( w[ u ] + w[ v ] + w[ v ' ] ) / ( w[ u,v ] + w[ v,v ' ] ) <=( w[ u ] +w[ v ] ) / w[ u , v ] ,成环的比例会更小,所以应只取一条比例最大的边,详见代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=500+100;
int n,m;
int x[MAXN];
int main()
{
//freopen("text.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
scanf("%d",&x[i]);
double ans=0.0;
for(int i=0;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
ans=max(ans,1.0*(x[u]+x[v])/w);
}
printf("%.15f\n",ans);
}
return 0;
}
DZY loves Fast Fourier Transformation, and he enjoys using it.
Fast Fourier Transformation is an algorithm used to calculate convolution. Specifically, if a, b and c are sequences with length n, which are indexed from 0 to n - 1, and

We can calculate c fast using Fast Fourier Transformation.
DZY made a little change on this formula. Now

To make things easier, a is a permutation of integers from 1 to n, and b is a sequence only containing 0 and 1. Given a and b, DZY needs your help to calculate c.
Because he is naughty, DZY provides a special way to get a and b. What you need is only three integers n, d, x. After getting them, use the code below to generate a and b.
//x is 64-bit variable; function getNextX() { x = (x * 37 + 10007) % 1000000007; return x; } function initAB() { for(i = 0; i < n; i = i + 1){ a[i] = i + 1; } for(i = 0; i < n; i = i + 1){ swap(a[i], a[getNextX() % (i + 1)]); } for(i = 0; i < n; i = i + 1){ if (i < d) b[i] = 1; else b[i] = 0; } for(i = 0; i < n; i = i + 1){ swap(b[i], b[getNextX() % (i + 1)]); } }
Operation x % y denotes remainder after division x by y. Function swap(x, y) swaps two values x and y.
The only line of input contains three space-separated integers n, d, x (1 ≤ d ≤ n ≤ 100000; 0 ≤ x ≤ 1000000006). Because DZY is naughty, x can't be equal to 27777500.
Output n lines, the i-th line should contain an integer ci - 1.
3 1 1
1 3 2
5 4 2
2 2 4 5 5
5 4 3
5 5 5 5 4
In the first sample, a is [1 3 2], b is [1 0 0], so c0 = max(1·1) = 1, c1 = max(1·0, 3·1) = 3, c2 = max(1·0, 3·0, 2·1) = 2.
In the second sample, a is [2 1 4 5 3], b is [1 1 1 0 1].
In the third sample, a is [5 2 1 4 3], b is [1 1 1 1 0].
题意:求
思路:用pos数组记录每个a[ i ]值的下标,同时用map记录第几个1在b数组的位置,其中map[ 0 ]是b数组中1的个数。那么用cnt控制循环次数,a[ i ]值从大到小更新c数组,对于
没有更新的c[ i ]值, 最后更新一下,详见代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=100000+100;
int n,d;
ll x;
int a[MAXN],b[MAXN],c[MAXN],pos[MAXN],map[MAXN];
int getNextX()
{
x=(x*37+10007)%1000000007;
return x;
}
void initAB()
{
for(int i=0;i<n;i++)
a[i]=i+1;
for(int i=0;i<n;i++)
swap(a[i],a[getNextX()%(i+1)]);
for(int i=0;i<n;i++)
if(i<d)
b[i]=1;
else
b[i]=0;
for(int i=0;i<n;i++)
swap(b[i],b[getNextX()%(i+1)]);
for(int i=0;i<n;i++)
pos[a[i]]=i;
for(int i=0;i<n;i++)
if(b[i])
map[++map[0]]=i;
}
int main()
{
//freopen("text1.txt","w",stdout);
scanf("%d%d%I64d",&n,&d,&x);
initAB();
int cnt=0;
for(int i=n;i>=1 && cnt<=10000000;i--)
for(int j=1;j<=map[0];j++,cnt++)
if(pos[i]+map[j]<n)
c[pos[i]+map[j]]=max(c[pos[i]+map[j]],i);
for(int i=0;i<n;i++)
if(!c[i])
for(int j=1;j<=map[0];j++)
{
if(i<map[j])
break;
else
c[i]=max(c[i],a[i-map[j]]);
}
for(int i=0;i<n;i++)
printf("%d\n",c[i]);
return 0;
}
DZY loves colors, and he enjoys painting.
On a colorful day, DZY gets a colorful ribbon, which consists of n units (they are numbered from 1 to n from left to right). The color of thei-th unit of the ribbon is i at first. It is colorful enough, but we still consider that the colorfulness of each unit is 0 at first.
DZY loves painting, we know. He takes up a paintbrush with color x and uses it to draw a line on the ribbon. In such a case some contiguous units are painted. Imagine that the color of unit i currently is y. When it is painted by this paintbrush, the color of the unit becomes x, and the colorfulness of the unit increases by |x - y|.
DZY wants to perform m operations, each operation can be one of the following:
- Paint all the units with numbers between l and r (both inclusive) with color x.
- Ask the sum of colorfulness of the units between l and r (both inclusive).
Can you help DZY?
The first line contains two space-separated integers n, m (1 ≤ n, m ≤ 105).
Each of the next m lines begins with a integer type (1 ≤ type ≤ 2), which represents the type of this operation.
If type = 1, there will be 3 more integers l, r, x (1 ≤ l ≤ r ≤ n; 1 ≤ x ≤ 108) in this line, describing an operation 1.
If type = 2, there will be 2 more integers l, r (1 ≤ l ≤ r ≤ n) in this line, describing an operation 2.
For each operation 2, print a line containing the answer — sum of colorfulness.
3 3 1 1 2 4 1 2 3 5 2 1 3
8
3 4 1 1 3 4 2 1 1 2 2 2 2 3 3
3 2 1
10 6 1 1 5 3 1 2 7 9 1 10 10 11 1 3 8 12 1 1 10 3 2 1 10
129
In the first sample, the color of each unit is initially [1, 2, 3], and the colorfulness is [0, 0, 0].
After the first operation, colors become [4, 4, 3], colorfulness become [3, 2, 0].
After the second operation, colors become [4, 5, 5], colorfulness become [3, 3, 2].
So the answer to the only operation of type 2 is 8.
题意:有n件制服,第i件衣服初始颜色为i。假设第i件衣服颜色当前为y,染色后为x,那么颜色的colorfulness就会增加 | x - y |
有两种操作: (1) 将 [ l , r ]之间的衣服染成x (2) 询问[ l , r ]之间的colorfulness和。
思路: 线段树成段更新,lazy标记。 只不过此题还需要一个lazy(程序中即col,记录该段衣服的颜色),之后就是基本的线段树了。但是需要注意的是update的时候,
即使segtree[ rt ].l == l && r == segtree[ rt ].r 也不能直接更新,因为必须要segtree[ rt ].col >0( 即该段衣服颜色均统一的时候)才能更新。详见代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
#define L(x) (x<<1)
#define R(x) (x<<1|1)
const int MAXN=100000+100;
int n,m;
struct node
{
int l,r;
ll sum,col,lazy;
ll size(){ return r-l+1; }
}segtree[MAXN<<2];
void build(int rt,int l,int r)
{
segtree[rt].l=l,segtree[rt].r=r;
segtree[rt].col=segtree[rt].sum=segtree[rt].lazy=0;
if(segtree[rt].l==segtree[rt].r)
{
segtree[rt].col=l;
return ;
}
int mid=(l+r)>>1;
build(L(rt),l,mid); build(R(rt),mid+1,r);
}
void push_down(int rt)
{
if(segtree[rt].l==segtree[rt].r)
return ;
if(segtree[rt].lazy)
{
segtree[L(rt)].lazy+=segtree[rt].lazy;
segtree[R(rt)].lazy+=segtree[rt].lazy;
segtree[L(rt)].sum+=segtree[L(rt)].size()*segtree[rt].lazy;
segtree[R(rt)].sum+=segtree[R(rt)].size()*segtree[rt].lazy;
segtree[rt].lazy=0;
}
if(segtree[rt].col)
segtree[L(rt)].col=segtree[R(rt)].col=segtree[rt].col;
}
void push_up(int rt)
{
if(segtree[L(rt)].col == segtree[R(rt)].col && segtree[L(rt)].col)
segtree[rt].col=segtree[L(rt)].col;
else
segtree[rt].col=0;
segtree[rt].sum=segtree[L(rt)].sum+segtree[R(rt)].sum;
}
void update(int rt,int l,int r,ll col)
{
push_down(rt);
if(segtree[rt].l == l && r == segtree[rt].r &&segtree[rt].col )
{
segtree[rt].sum+=segtree[rt].size()*abs(segtree[rt].col-col);
segtree[rt].lazy+=abs(segtree[rt].col-col);
segtree[rt].col=col;
return ;
}
int mid=(segtree[rt].l+segtree[rt].r)>>1;
if(l>mid)
update(R(rt),l,r,col);
else if(r<=mid)
update(L(rt),l,r,col);
else
{
update(L(rt),l,mid,col);
update(R(rt),mid+1,r,col);
}
push_up(rt);
}
ll query(int rt,int l,int r)
{
push_down(rt);
if( l == segtree[rt].l && r == segtree[rt].r)
return segtree[rt].sum;
int mid=(segtree[rt].l+segtree[rt].r)>>1;
if(l>mid)
return query(R(rt),l,r);
else if(r<=mid)
return query(L(rt),l,r);
else
return query(L(rt),l,mid)+query(R(rt),mid+1,r);
}
int main()
{
//freopen("text.txt","r",stdin);
int cmd,l,r;
ll x;
while(~scanf("%d%d",&n,&m))
{
build(1,1,n);
while(m--)
{
scanf("%d%d%d",&cmd,&l,&r);
if(cmd==1)
{
scanf("%I64d",&x);
update(1,l,r,x);
}
else
printf("%I64d\n",query(1,l,r));
}
}
return 0;
}