CF Round #423 Div. 2 C. String Reconstruction D. High Load 【思维】

来源:互联网 发布:iphone淘宝 编辑:程序博客网 时间:2024/05/16 14:48

C. String Reconstruction


time limit per test 2 seconds

memory limit per test     256 megabytes


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

Ivan knows some information about the strings. 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 reconstructlexicographically minimal strings 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 integern (1 ≤ n ≤ 105) — the number of stringsIvan remembers.

The nextn lines contain information about the strings. The i-th of these lines contains non-emptystring 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 106,1 ≤ xi, j ≤ 106,1 ≤ 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

Printlexicographically minimal string that fits all the information Ivan remembers.

Examples

Input

3
a 4 1 3 5 7
ab 2 1 5
ca 1 4

Output

abacaba

Input

1
a 1 3

Output

aaa

Input

3
ab 1 1
aba 1 3
ab 2 3 5

Output

ababab

 

【题意】给出一个字符串的若干子串出现的位置,要求还原字符串,并使其字典序最小。

【分析】直接想到暴力做,按顺序直接照着子串填进去,没有填过的地方用'a'填充(使字典序最小),但果断超时。所以我们考虑优化方法,由于在填充的时候很多位置发生了重复填充,由于题目说了,所给信息间不会冲突,所以已经填充过的地方再去填充显然是多余的。所以我们考虑对每个子串出现的位置进行排序,然后再填充,填过的地方就不会再被填充了,这样就解决了上面的冗余问题。

时间复杂度接近O(n)



(499ms)

#include <cstdio>#include <string>#include <iostream>#include <queue>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 1000005;const int mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;struct node{    int pos,id;}a[maxn];bool cmp(const node &a,const node &b){    return a.pos<b.pos;}string  s[maxn];int main(){    int n,k,x;    int cnt=0;    scanf("%d",&n);    for(int i=0;i<n;i++)    {        cin>>s[i];        scanf("%d",&k);        for(int j=0;j<k;j++)        {            scanf("%d",&x);            a[cnt].pos=x;            a[cnt++].id=i;        }    }    sort(a,a+cnt,cmp);    string ans;    int now=1;    for(int i=0;i<cnt;i++)    {        while(now<a[i].pos)        {            ans+='a';            now++;        }        for(int j=now-a[i].pos;j<s[a[i].id].length();j++)  //这里的起点是优化之处        {            ans+=s[a[i].id][j];            now++;        }    }    cout<<ans<<endl;}


方法二:还有一种避免重复填充的方法就是利用并查集,把已经填充过的位置跟它的下一位置合并,具体可见传送门,思路类似

(311ms)

#include <cstdio>#include <map>#include <iostream>#include <queue>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 2000005;const int mod = 20090717;const int INF = 0x3f3f3f3f;const double eps = 1e-6;char ans[maxn];char s[maxn];int pre[maxn];int find(int x){    int t,r=x;    while(pre[x]!=x)    {        x=pre[x];    }    while(r!=x)    {        t=pre[r];        pre[r]=x;        r=t;    }    return x;}void join(int a,int b){    int A,B;    A=find(a);    B=find(b);    if(A>B)    {        pre[B]=A;    }    else pre[A]=B;}int main(){    int n,k,x;    int Max=1;    mst(ans,' ');    for(int i=1;i<maxn;i++)    {        pre[i]=i;    }    scanf("%d",&n);    for(int i=0;i<n;i++)    {        scanf("%s%d",s,&k);        int len=strlen(s);        for(int j=0;j<k;j++)        {            scanf("%d",&x);            Max=max(Max,x+len-1);            int temp=x;            x=find(x);            while(x<=temp+len-1)            {                ans[x]=s[x-temp];                x=find(x);                if(x<=temp+len-1)                    join(x,x+1);            }        }    }    for(int i=1;i<=Max;i++)    {        if(ans[i]==' ')            printf("a");        else printf("%c",ans[i]);    }    puts("");}


D. High Load

time limit per test 2 seconds

memory limit per test     512 megabytes


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

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

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

Input

The first line contains two integersn and k (3 ≤ n ≤ 2·105,2 ≤ 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 networkwithn nodes and k exit-nodes within the given constraints.

Output

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

Ifthere are multiple answers, print any of them.

Examples

Input

3 2

Output

2
1 2
2 3

Input

5 3

Output

3
1 2
2 3
3 4
3 5

Note

In the first example the only network is shown on the leftpicture.

In the second example one of optimal networks is shown on theright picture.

Exit-nodes are highlighted.

 


【题意】给出n个点,其中k个点为exit-node(记为单向点,其余点为多向点),单向点只能连接一个点,而多向点能连接多个点,问怎么样连接能使任意两个点之间的距离的最大值最小化,输出最小值及连接方案。

【分析】首先,由于要求最大距离最小化,所以我们应该尽量让所有点形成一个环状。由于k>=2,即单向点的个数一定大于2,而且k<=n-1,即多向点的个数一定大于1,所以我们可以用一个多向点连接k个单向点,这个环的每圈最多有个点,然后再在外围加点,加点的过程其实就是把内圈的单向点转化为多向点(双向),再在它的外面加上一个单向点。

那么最小的最大距离是多少呢?我们分下面三种情况考虑:

  1. 每个环刚好填满,那么dis=(n-1)/k*2
  2. 每个环满后多出了一个点,那么dis=(n-1)/k*2+1
  3. 其余情况都是dis=(n-1)/k*2+2

可以看图深化理解


最后的连接方案从内圈往外依次标号即可。


#include <cstdio>#include <string>#include <iostream>#include <queue>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 1000005;const int mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;int main(){    int n,k;    scanf("%d%d",&n,&k);    int num=(n-1)/k;    int ans;    if((n-1)%k==0)    {        ans=num*2;    }    else if((n-1)%k==1)    {        ans=num*2+1;    }    else ans=num*2+2;    printf("%d\n",ans);    for(int i=2;i<=k+1;i++)    {        printf("%d %d\n",1,i);    }    for(int i=k+2;i<=n;i++)    {        printf("%d %d\n",i-k,i);    }    return 0;}





阅读全文
0 0
原创粉丝点击