Codeforces Round #423(Div.2)

来源:互联网 发布:淘宝信用借贷逾期 编辑:程序博客网 时间:2024/06/17 11:38

这是我第一次在半夜爬起来打的比赛。虽然最后的结果不那么近人意,但还是积累了不少经验的。

23:30

WenDavid打了3次QQ电话,终于把我这个正在熟睡的懒虫给叫醒了(话说比赛在24:45才开始,他辣么早叫我干啥。。。)。不过就算我那时不醒,我也在24点调了4个闹钟了。。。无论如何,在朦胧之中,我终于打开了电脑。

0:00

无聊死了。在班群上发了'Hi‘,居然还有人没有睡觉,和我说了一会话。

0:45

比赛开始了。第1,2题:唉,大水题!7分钟A了第一题,第23分钟就A了两题。

1:20

第三题,貌似有点难度!想了一会儿,诶,不是线段树吗?用8min搞了个线段树。。。。不对,会超时!正当我想把程序删掉时,WenDavid又说可以用线段树做,两人一起想了15min,终于搞定了。。。“Wrong Answer on pretest 5”??Excuse me???数组没开够!!!唉,这就是没看清题目的后果啊!!!可WenDavid由于刚经历了“恐怖的初三”,连Segment-Tree都忘记如何打了。无奈之下,我把程序给了他。

2:45

第四题,好像很难得样子唉。在草稿纸上画了几张图,终于搞出来了。样例过了,可时间也过了。。。再给多1min就好了。。。。。。


总结:还是要多去做题,巩固基础,提高手速!!!



题解:


A. Restaurant Tables
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

In a small restaurant there are a tables for one person and b tables for two persons.

It it known that n groups of people come today, each consisting of one or two people.

If a group consist of one person, it is seated at a vacant one-seater table. If there are none of them, it is seated at a vacant two-seater table. If there are none of them, it is seated at a two-seater table occupied by single person. If there are still none of them, the restaurant denies service to this group.

If a group consist of two people, it is seated at a vacant two-seater table. If there are none of them, the restaurant denies service to this group.

You are given a chronological order of groups coming. You are to determine the total number of people the restaurant denies service to.

Input

The first line contains three integers na and b (1 ≤ n ≤ 2·1051 ≤ a, b ≤ 2·105) — the number of groups coming to the restaurant, the number of one-seater and the number of two-seater tables.

The second line contains a sequence of integers t1, t2, ..., tn (1 ≤ ti ≤ 2) — the description of clients in chronological order. If ti is equal to one, then the i-th group consists of one person, otherwise the i-th group consists of two people.

Output

Print the total number of people the restaurant denies service to.

Examples
input
4 1 21 2 1 1
output
0
input
4 1 11 1 2 1
output
2

【思路】

模拟即可。设a为剩下一人座的台数,b为剩下空的二人座的台数,c为剩下有一个人的二人座的台数。模拟统计即可。时间复杂度O(n)。

【程序】

#include <cstdio>#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <string>#include <ctime>#include <fstream>#include <map>#include <queue>#include <deque>#include <stack>#include <set>#include <vector>using namespace std;int n,a,b,c,x,ans;int main(){scanf("%d%d%d",&n,&a,&b);for(int i=0;i<n;i++){scanf("%d",&x);if(x==1)if(a)a--;elseif(b){b--;c++;}elseif(c)c--;elseans++;elseif(b)b--;elseans+=2;}printf("%d\n",ans);return 0;}

B. Black Square
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Polycarp has a checkered sheet of paper of size n × m. Polycarp painted some of cells with black, the others remained white. Inspired by Malevich's "Black Square", Polycarp wants to paint minimum possible number of white cells with black so that all black cells form a square.

You are to determine the minimum possible number of cells needed to be painted black so that the black cells form a black square with sides parallel to the painting's sides. All the cells that do not belong to the square should be white. The square's side should have positive length.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 100) — the sizes of the sheet.

The next n lines contain m letters 'B' or 'W' each — the description of initial cells' colors. If a letter is 'B', then the corresponding cell is painted black, otherwise it is painted white.

Output

Print the minimum number of cells needed to be painted black so that the black cells form a black square with sides parallel to the painting's sides. All the cells that do not belong to the square should be white. If it is impossible, print -1.

Examples
input
5 4WWWWWWWBWWWBWWBBWWWW
output
5
input
1 2BB
output
-1
input
3 3WWWWWWWWW
output
1
Note

In the first example it is needed to paint 5 cells — (2, 2)(2, 3)(3, 2)(3, 3) and (4, 2). Then there will be a square with side equal to three, and the upper left corner in (2, 2).

In the second example all the cells are painted black and form a rectangle, so it's impossible to get a square.

In the third example all cells are colored white, so it's sufficient to color any cell black.


【思路】

对于每一个黑色点(i,j),标记出四至点,即最上u(min(i)),最下d(max(i)),最左l(min(j)),最右r(max(j)),然后依题意可知:正方形的边长就是max(d-u+1,r-l+1);

然后答案就是正方形的面积-黑色方块的数量。

注意特殊情况的处理:

1,全部白色输出1,

2,如果正方形的边长大于n或m,输出-1。

【程序】

#include <cstdio>#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <string>#include <ctime>#include <fstream>#include <map>#include <queue>#include <deque>#include <stack>#include <set>#include <vector>using namespace std;#define INF 0x7ffffffint n,m;char ch;int sum,len;int u,d,l,r;int main(){scanf("%d%d",&n,&m);sum = 0;u = l = INF;d = r = -INF;for(int i=1;i<=n;i++){ch = getchar();for(int j=1;j<=m;j++){ch = getchar();if(ch == 'B') {u = min(u,i);d = max(d,i);l = min(l,j);r = max(r,j);sum++;//统计黑色个数 }}}if(sum == 0)//全是白色的情况 {printf("1\n");return 0;}len = max(d-u+1 , r-l+1);if(len>n || len>m)//正方形边长过大的情况 {printf("-1\n");return 0;}printf("%d\n",len * len - sum);//一般情况return 0;}


C. String Reconstruction
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Ivan had string s consisting of small English letters. However, his friend Julia decided to make fun of him and hid the string s. Ivan preferred making a new string to finding the old one.

Ivan knows some information about the string s. Namely, he remembers, that string ti occurs in string s at least ki times or more, he also remembers exactly ki positions where the string ti occurs in string s: these positions are xi, 1, xi, 2, ..., xi, ki. He remembers n such strings ti.

You are to reconstruct lexicographically minimal string s such that it fits all the information Ivan remembers. Strings ti and string s consist of small English letters only.

Input

The first line contains single integer n (1 ≤ n ≤ 105) — the number of strings Ivan remembers.

The next n lines contain information about the strings. The i-th of these lines contains non-empty string ti, then positive integer ki, which equal to the number of times the string ti occurs in string s, and then ki distinct positive integers xi, 1, xi, 2, ..., xi, ki in increasing order — positions, in which occurrences of the string ti in the string s start. It is guaranteed that the sum of lengths of strings ti doesn't exceed 1061 ≤ xi, j ≤ 1061 ≤ ki ≤ 106, and the sum of all ki doesn't exceed 106. The strings ti can coincide.

It is guaranteed that the input data is not self-contradictory, and thus at least one answer always exists.

Output

Print lexicographically minimal string that fits all the information Ivan remembers.

Examples
input
3a 4 1 3 5 7ab 2 1 5ca 1 4
output
abacaba
input
1a 1 3
output
aaa
input
3ab 1 1aba 1 3ab 2 3 5
output
ababab


【思路1】

解法1:最暴力的方法,一开始把字符串s的每一个字符全设为'a',对于每一个字符串每一个出现的位置都进行修改。超时!

解法2:题目表示不会自相矛盾,那么我们可以标记一下字符串的哪个位置已经修改过了,然后判断是否已经全部修改。这个可以用一个线段树去维护。如果某个区间没有全部被修改过,那么全部修改。对于很坑的数据,还是会超时。

解法3:既然不可以全部进行修改,那么可以在线段树的过程中修改吗?答案是可以的。则时间复杂度是O(LlogL)。

具体看程序:

【程序1】

#include <cstdio>#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <string>#include <ctime>#include <fstream>#include <map>#include <queue>#include <deque>#include <stack>#include <set>#include <vector>using namespace std;#define Maxn 2000010//注意!字符串的长度最大有可能是2*10^6!!!char s[Maxn];//s是当前的字符串 char ans[Maxn];int n,k,le,ri;int fp;struct Tnode{//Segment-Tree int lc,rc;int l,r;int set;//当set = 1时,表示这个区间已被修改 };Tnode tr[Maxn<<2];int build(int l,int r)//建树 {fp++;tr[fp].l = l; tr[fp].r = r;tr[fp].set = 0;int now = fp;if(l<r){int mid = (l+r)>>1;tr[now].lc = build(l,mid);tr[now].rc = build(mid+1,r);}else{tr[now].lc = tr[now].rc = 0;}return now;}void update(int u,int l,int r){if(tr[u].set) return;//如果整个区间都已经修改过了,那么与区间[l,r]相关联的点也一定修改过了 if(tr[u].l == tr[u].r)//如果是叶子节点 {ans[tr[u].l] = s[tr[u].l - l];//修改tr[u].set = true;return;}int mid = (tr[u].l + tr[u].r)>>1;if(l<=mid) update(tr[u].lc,l,r);if(mid<r) update(tr[u].rc,l,r);if(tr[tr[u].lc].set == true && tr[tr[u].rc].set == true) tr[u].set = true;//维护set }int main(){int maxx = 0;scanf("%d",&n);build(1,Maxn-1);for(int i=1;i<=Maxn;i++) ans[i] = 'a';for(int i=1;i<=n;i++){scanf("%s%d",s,&k);int len = strlen(s);for(int j=0;j<k;j++){scanf("%d",&le);ri = le + len - 1;maxx = max(maxx,ri);update(1,le,ri);}}for(int i=1;i<=maxx;i++) printf("%c",ans[i]);return 0;}

【思路2】

用并查集维护,每次找最右边的没有修改过的进行修改即可。

【程序2】

#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int Maxn = 3000005;int fa[Maxn];char s[Maxn];char st[Maxn];int x;int find(int x){if(x == fa[x]) return x;return fa[x] = find(fa[x]);}int main(){    int n,m;        for(int i=0;i<Maxn;i++)        fa[i] = i;        memset(s,0,sizeof(s));    int maxx = 0;        scanf("%d",&n);    while(n--){        scanf("%s",st);        scanf("%d",&m);        int len = strlen(st);                for(int j=0;j<m;j++){            scanf("%d",&x);            x--;            maxx=max(x+len,maxx);                        int tmp = find(x);            for(;tmp-x<len;tmp=fa[tmp]=find(tmp+1))                s[tmp] = st[tmp-x];        }    }        for(int i=0;i<maxx;i++)        if(s[i]==0)            putchar('a');        else            printf("%c",s[i]);    printf("\n");    return 0;}


D. High Load
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Arkady needs your help again! This time he decided to build his own high-speed Internet exchange point. It should consist of n nodes connected with minimum possible number of wires into one network (a wire directly connects two nodes). Exactly k of the nodes should be exit-nodes, that means that each of them should be connected to exactly one other node of the network, while all other nodes should be connected to at least two nodes in order to increase the system stability.

Arkady wants to make the system as fast as possible, so he wants to minimize the maximum distance between two exit-nodes. The distance between two nodes is the number of wires a package needs to go through between those two nodes.

Help Arkady to find such a way to build the network that the distance between the two most distant exit-nodes is as small as possible.

Input

The first line contains two integers n and k (3 ≤ n ≤ 2·1052 ≤ k ≤ n - 1) — the total number of nodes and the number of exit-nodes.

Note that it is always possible to build at least one network with n nodes and k exit-nodes within the given constraints.

Output

In the first line print the minimum possible distance between the two most distant exit-nodes. In each of the next n - 1 lines print two integers: the ids of the nodes connected by a wire. The description of each wire should be printed exactly once. You can print wires and wires' ends in arbitrary order. The nodes should be numbered from 1 to n. Exit-nodes can have any ids.

If there are multiple answers, print any of them.

Examples
input
3 2
output
21 22 3
input
5 3
output
31 22 33 43 5

【题意】

有n个点,其中有k个Exit-nodes节点。用一些边把这n个点连起来,使其连通。限制:Exit-nodes节点必须连向其他点(即不能自环 ),非Exit-nodes节点必须连两条边以上。且最远点的距离要最少。输出一个符合要求的图即可。

【思路】

一开始以为是二分之类的东西。。。。。。

可以发现,最后是变成了一棵树。而Exit-nodes节点是叶子节点。也就是说,有k个叶子节点,n-k个非叶子节点,且树中距离最远的点对的距离最少即可。

其实我们可以发现:树中距离最远的两个点一定都是叶子节点(不考虑特殊情况,而题目的条件刚好把所有特殊情况避开了),也就是说,树要尽量平衡,则其深度要最小。

我们可以如此构造一棵树:


那么,就可以很容易构造这棵树了。

时间复杂度O(n)。

【程序】

#include <cstdio>#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <string>#include <ctime>#include <fstream>#include <map>#include <queue>#include <deque>#include <stack>#include <set>#include <vector>using namespace std;int n,k;int main(){scanf("%d%d",&n,&k);int maxnum=((n-1)/k)<<1;if((n-1)%k==1)maxnum++;else if((n-1)%k>=2)maxnum+=2;printf("%d\n",maxnum);for(int i=1;i<=k;i++) printf("%d %d\n",1,i+1);//第一行 for(int i=1;i<(n-1)/k;i++)for(int j=1;j<=k;j++) printf("%d %d\n",i*k-k+j+1,i*k+j+1);//其他行 for(int i=1;i<=(n-1)%k;i++) printf("%d %d\n",n-k-i+1,n-i+1);//剩下来的 return 0;}

E. DNA Evolution
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Everyone knows that DNA strands consist of nucleotides. There are four types of nucleotides: "A", "T", "G", "C". A DNA strand is a sequence of nucleotides. Scientists decided to track evolution of a rare species, which DNA strand was string s initially.

Evolution of the species is described as a sequence of changes in the DNA. Every change is a change of some nucleotide, for example, the following change can happen in DNA strand "AAGC": the second nucleotide can change to "T" so that the resulting DNA strand is "ATGC".

Scientists know that some segments of the DNA strand can be affected by some unknown infections. They can represent an infection as a sequence of nucleotides. Scientists are interested if there are any changes caused by some infections. Thus they sometimes want to know the value of impact of some infection to some segment of the DNA. This value is computed as follows:

  • Let the infection be represented as a string e, and let scientists be interested in DNA strand segment starting from position l to position r, inclusive.
  • Prefix of the string eee... (i.e. the string that consists of infinitely many repeats of string e) is written under the string s from position l to position r, inclusive.
  • The value of impact is the number of positions where letter of string s coincided with the letter written under it.

Being a developer, Innokenty is interested in bioinformatics also, so the scientists asked him for help. Innokenty is busy preparing VK Cup, so he decided to delegate the problem to the competitors. Help the scientists!

Input

The first line contains the string s (1 ≤ |s| ≤ 105) that describes the initial DNA strand. It consists only of capital English letters "A", "T", "G" and "C".

The next line contains single integer q (1 ≤ q ≤ 105) — the number of events.

After that, q lines follow, each describes one event. Each of the lines has one of two formats:

  • 1 x c, where x is an integer (1 ≤ x ≤ |s|), and c is a letter "A", "T", "G" or "C", which means that there is a change in the DNA: the nucleotide at position x is now c.
  • 2 l r e, where lr are integers (1 ≤ l ≤ r ≤ |s|), and e is a string of letters "A", "T", "G" and "C" (1 ≤ |e| ≤ 10), which means that scientists are interested in the value of impact of infection e to the segment of DNA strand from position l to position r, inclusive.
Output

For each scientists' query (second type query) print a single integer in a new line — the value of impact of the infection on the DNA.

Examples
input
ATGCATGC42 1 8 ATGC2 2 6 TTT1 4 T2 2 6 TA
output
824
input
GAGTTGTTAA62 3 4 TATGGTG1 1 T1 6 G2 5 9 AGTAATA1 10 G2 2 6 TTGT
output
031


【题意】

给定一个字符串(下标从1开始),与两种操作:1:把下标为x的字符修改为c。2:询问在区间[l,r]中,把字符串e重复无限遍后与其相同的个数(具体看样例)。

【思路】

首先用的就是暴力了。对于每一次修改与查询都暴力解决。时间复杂度最坏是O(n^2)。超时。

对于有修改和查询的题目,一般都可以用数据结构来优化。对于本题,是单点修改,区间查询。所以可以用树状数组来解决。

现在问题来了:我们查询的是总和,可字符串的字符不相等,该怎样查询呢?

先考虑特殊情况:

如果字符串e的长度为1,那就简单了。相当于求区间[l,r]有多少个是与该字符相同的。

可以建4棵树状数组。分别存A,C,T,G四个字母的状态。如图:


那么现在考虑一般情况(当e的长度>1时):其实我们可以把查询分成len(e)次查询,第i次查询就是看s[L+i],s[L+i+len(e)],s[L+i+2*len(e)]……(其中L是区间的起始点)有多少与这个字符e[i]相同。

一般的情况是否可以像特殊情况那样做呢???

我们发现,这样做就是每隔len(e)就出现一次。又该怎样处理呢?

注意到题目中查询的字符串e的长度十分小,也就是说是否可以从这里入手呢?

可以设f[a]为当e的长度为a时的树状数组。假设a=3,那么就是下标1,4,7,10……的前缀和(树状数组其实就是维护动态的前缀和)了。

那么(2,5,8,11……)和(3,6,9,12……)该怎么办呢?很明显要加多一维。用f[a][b]表示当e的长度为a且它的位置为b的树状数组。这个位置b也很容易求:相当于其所在下标Mod a。

那么这样一共需要(1+2+3……+10) = 55 组(注意是组)树状数组。若经过某些处理,可以省掉约一般空间,这里略去。



对于不同的字符串长度,我们都要建立许多棵树状数组。而对于不同的位置(如图),我们也要建立树状数组。则用f[a][b][c]来表示每次跳的长度(字符串长)为a,位置为b,字符编号为c的树状数组。

【时间复杂度的分析】

一共要建(1+2+3+……+10) * 4  = 55 * 4 = 220个树状数组,则时间复杂度为O(10LlogL + Q1*10*2*logL + 2*sum(Length(ei)) * logL) = O((10L+20Q1+2*sum(Length(ei)))logL)。(因为时间上有点紧,所以最好不要忽略常数)

其中L为字符串长度。Q1为修改的次数,Sum(Length(ei))为查询字符串的总长度。

则最大的时间复杂度约为O(6 * 10 ^ 7),实现2s,可以通过。

【程序】

#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>using namespace std;#define lowbit(x) x & (-x)#define Maxn 100010int f[11][11][4][Maxn];int n;char s[Maxn];char c[Maxn];int ch(char s)//字符编号 {if(s=='A') return 0;else if(s=='C') return 1;else if(s=='T') return 2;else if(s=='G') return 3;return -1;}void Add(int *tr,int x,int d)//树状数组修改 {for(;x <= n;x+=lowbit(x)){tr[x] += d;}}int Sum(int *tr,int x)//树状数组查询前缀和 {if(x == 0) return 0;int s = 0;while(x){s += tr[x];x -= lowbit(x);}return s;}int main(){scanf("%s",s);n = strlen(s);for(int i=n-1;i>=0;i--) s[i+1] = s[i];s[0] = 0;for(int i=1;i<=n;i++)for(int j=1;j<=10;j++)Add(f[j][i%j][ch(s[i])] , i , 1);int q,x,d,l,r;scanf("%d",&q);while(q--){scanf("%d",&x);if(x == 1)//修改部分 {scanf("%d%s",&d,c);for(int i=1;i<=10;i++)Add(f[i][d%i][ch(s[d])] , d , -1);//删除 s[d] = c[0];for(int i=1;i<=10;i++)Add(f[i][d%i][ch(s[d])] , d , 1);//增加 }else//查询部分 {scanf("%d%d%s",&l,&r,c);int len = strlen(c);int ans = 0;for(int i=0;i<len;i++)ans += Sum(f[len][(l+i) % len][ch(c[i])],r) - Sum(f[len][(l+i) % len][ch(c[i])],l-1);//区间求和printf("%d\n",ans);}}return 0;}


F. Best Edge Weight
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given a connected weighted graph with n vertices and m edges. The graph doesn't contain loops nor multiple edges. Consider some edge with id i. Let's determine for this edge the maximum integer weight we can give to it so that it is contained in all minimum spanning trees of the graph if we don't change the other weights.

You are to determine this maximum weight described above for each edge. You should calculate the answer for each edge independently, it means there can't be two edges with changed weights at the same time.

Input

The first line contains two integers n and m (2 ≤ n ≤ 2·105n - 1 ≤ m ≤ 2·105), where n and m are the number of vertices and the number of edges in the graph, respectively.

Each of the next m lines contains three integers uv and c (1 ≤ v, u ≤ nv ≠ u1 ≤ c ≤ 109) meaning that there is an edge between vertices u and v with weight c.

Output

Print the answer for each edge in the order the edges are given in the input. If an edge is contained in every minimum spanning tree with any weight, print -1 as the answer.

Examples
input
4 41 2 22 3 23 4 24 1 3
output
2 2 2 1 
input
4 31 2 22 3 23 4 2
output
-1 -1 -1 

【题意】

给定一个图,求出每一条边可以修改成的最大整数权值,使得在不修改其他边权的前提下,这条边在所有的最小生成树里。

【思路】

题目关系到最小生成树,那就先建一棵最小生成树吧。举个例子:这个最小生成树是这样的:


如图:实线的边是最小生成树的边,虚线的边不是最小生成树的边。

我们要分两种情况来考虑:

1,虚边的答案:

如果虚边变成了最小生成树的边,则环上的最大的边要变成虚边。即:


可以发现,这个环的最顶端即是虚边的两点在最小生成树上的LCA。那么,我们就可以用倍增算法来求。只需加多一个数组disMax[i][j],表示节点i到其2^j的祖先的路径中最大的边权。LCA最后返回的是这个环的最大边权。

如果要想这条虚边成为最小生成树的边,那么就要刚好比最大边权少1。

2,实边的答案:

可以发现,只有虚边才能影响实边的答案。那么虚边有影响了那些实边呢?

还可以发现,又是与它们的LCA所组成的环的所有边中先关。如果这些边想要是最小生成树的边,那么它的权值就要刚刚小于dis(u,v),即虚边的权值减1。

但是:还有一种情况:


这条边重复了,易得这条边的答案是'所有与它相关的虚边的权值的最小值减1'。

但是!如果这样重复计算,每次的时间复杂度高达O(m),就有可能会超时了。

是否可以从小到大枚举虚边,然后把未标记且经过的实边都标记,然后跳过已标记的实边?

用并查集优化即可。

则总的时间复杂度O(nlogn)。

【程序】

#include <cstdio>#include <iostream>#include <cstring>#include <string>#include <algorithm>#include <vector>#include <cmath>#include <set>using namespace std;#define Maxn 200010struct Edge{int x,y,val,id;bool operator < (const Edge e) const{return val < e.val;}};int n,m;Edge e[Maxn];int tid[Maxn];int ans[Maxn];bool vis[Maxn];void init(){scanf("%d%d",&n,&m);for(int i=0;i<m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].val),e[i].id = i;}int fa[Maxn];int find(int x){if(x!=fa[x]) fa[x] = find(fa[x]);return fa[x];}void kruskal(){memset(vis,0,sizeof(vis));sort(e,e+m);for(int i=1;i<=n;i++) fa[i] = i;int sum = 0;for(int i=0;i<m;i++){int lx = find(e[i].x),ly = find(e[i].y);if(lx!=ly){fa[lx] = ly;vis[e[i].id] = true;sum++;if(sum == n-1) break;}}}#define M 22vector<Edge> adj[Maxn];int gra[Maxn][M+2],disMax[Maxn][M+2];int dep[Maxn];void initLCA(){for(int i=0;i<m;i++)if(vis[e[i].id] == true){adj[e[i].x].push_back((Edge){e[i].x,e[i].y,e[i].val,e[i].id});adj[e[i].y].push_back((Edge){e[i].y,e[i].x,e[i].val,e[i].id});}dep[0] = -1;dep[1] = 1;}void dfs(int u,int pre){int len = adj[u].size();for(int i=1;i<=M;i++){gra[u][i] = gra[gra[u][i-1]][i-1];disMax[u][i] = max(disMax[u][i-1],disMax[gra[u][i-1]][i-1]);if(!gra[u][i]) break;}for(int i=0;i<len;i++)if(adj[u][i].y!=pre){int to = adj[u][i].y;dep[to] = dep[u] + 1;gra[to][0] = u;tid[to] = adj[u][i].id;disMax[to][0] = adj[u][i].val;dfs(to,u);}}int LCA(int x,int y){int Maxx = 0;if(dep[x]>dep[y]) swap(x,y);for(int i=M;i>=0;i--)if(dep[gra[y][i]] >= dep[x]){Maxx = max(Maxx,disMax[y][i]);y = gra[y][i];}for(int i=M;i>=0;i--)if(gra[x][i] != gra[y][i]){Maxx = max(Maxx,max(disMax[x][i],disMax[y][i]));x = gra[x][i]; y = gra[y][i];}if(x!=y) Maxx = max(Maxx,max(disMax[x][0],disMax[y][0]));return Maxx;}void GetAns(){int u,v,val,id;for(int i=0;i<=n;i++) fa[i] = i;for(int i=0;i<m;i++)if(!vis[e[i].id]){u = e[i].x; v = e[i].y; val = e[i].val; id = e[i].id;ans[id] = LCA(u,v);for(;;){u = find(u); v = find(v);if(u == v) break;if(dep[u] < dep[v]) swap(u,v);ans[tid[u]] = max(ans[tid[u]],val);fa[u] = find(gra[u][0]);}}}void Print(){for(int i=0;i<m;i++) printf("%d ",ans[i] - 1);return;}int main(){init();kruskal();initLCA();dfs(1,0);GetAns();Print();return 0;}


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小米6进海水了怎么办 小米手机掉海水里怎么办 苹果7进海水了怎么办 7p手机进海水怎么办 育海参苗出现红细菌怎么办 苹果手机掉进厕所怎么办 2个月的婴儿肺炎怎么办 甜甜圈珊瑚脱骨怎么办 宝宝吃了生物球怎么办 狗尾巴被剪掉了怎么办 魟鱼尾巴刺了怎么办 狗咬过了24小时怎么办 狗咬超过24小时怎么办 狗咬超过48小时怎么办 狗咬超过72小时怎么办 狗抓超过24小时怎么办 龙须树叶子发黄怎么办? 车被广告牌砸了怎么办 开花店压力好大怎么办 快成熟葡萄软果怎么办 木本叶长白斑点了怎么办 天猫卖家超过72小时未发货怎么办 淘宝超过72小时不发货怎么办 鸿运当头干叶了怎么办 百合枝干长歪了怎么办 植物主干长歪了怎么办 钱兜子花叶子黄怎么办 丝瓜有苦味吃了怎么办 吃了苦的西葫芦怎么办 吃了苦的西葫芦中毒怎么办 吃了一点苦丝瓜怎么办 丝瓜苦味我吃了怎么办? 小孩牙地包天怎么办 小孩的牙地包天怎么办 小孩牙是地包天怎么办 布偶猫生宝宝时怎么办 仔猪拉稀打针喂药都不好怎么办 qq群宠物沉眠怎么办 单位不给开离职证明怎么办 电梯年检报告丢了怎么办 小学生养成夜训交怎么办?