【CF731D】80-th Level Archeology

考古学家在金字塔的密室发现了一个独特的锁,解锁需要将一系列由特殊符号组成的单词按字典序排列。每旋转一次开关,符号会按照特定规则循环变化。题目要求找出最小的旋转次数使单词序列字典序排序,或者判断不可能完成。输入包含单词数量和符号种类,以及每个单词的描述。通过树状数组和差分方法计算所需操作次数,若存在使得序列排序的操作,则输出该次数,否则输出-1。
摘要由CSDN通过智能技术生成

题目

展开
题目描述
Archeologists have found a secret pass in the dungeon of one of the pyramids of Cycleland. To enter the treasury they have to open an unusual lock on the door. The lock consists of nn words, each consisting of some hieroglyphs. The wall near the lock has a round switch. Each rotation of this switch changes the hieroglyphs according to some rules. The instruction nearby says that the door will open only if words written on the lock would be sorted in lexicographical order (the definition of lexicographical comparison in given in notes section).

The rule that changes hieroglyphs is the following. One clockwise rotation of the round switch replaces each hieroglyph with the next hieroglyph in alphabet, i.e. hieroglyph xx ( 1<=x<=c-11<=x<=c−1 ) is replaced with hieroglyph (x+1)(x+1) , and hieroglyph cc is replaced with hieroglyph 11 .

Help archeologist determine, how many clockwise rotations they should perform in order to open the door, or determine that this is impossible, i.e. no cyclic shift of the alphabet will make the sequence of words sorted lexicographically.

输入格式
The first line of the input contains two integers nn and cc ( 2<=n<=5000002<=n<=500000 , 1<=c<=10^{6}1<=c<=10
6
) — the number of words, written on the lock, and the number of different hieroglyphs.

Each of the following nn lines contains the description of one word. The ii -th of these lines starts with integer l_{i}l
i

( 1<=l_{i}<=5000001<=l
i

<=500000 ), that denotes the length of the ii -th word, followed by l_{i}l
i

integers w_{i,1}w
i,1

, w_{i,2}w
i,2

, …, w_{i,li}w
i,li

( 1<=w_{i,j}<=c1<=w
i,j

<=c ) — the indices of hieroglyphs that make up the ii -th word. Hieroglyph with index 11 is the smallest in the alphabet and with index cc — the biggest.

It’s guaranteed, that the total length of all words doesn’t exceed 10^{6}10
6
.

输出格式
If it is possible to open the door by rotating the round switch, print integer xx ( 0<=x<=c-10<=x<=c−1 ) that defines the required number of clockwise rotations. If there are several valid xx , print any of them.

If it is impossible to open the door by this method, print -1−1 .

题意翻译
有n个数列,每个数列长度可能不一样,同时有一个c,你有一种操作,让这n个数列中所有小于c的数都加1,所有等于c的数变成0.问你最少可以操作几次可以让这n个数列满足字典序

输入输出样例
输入 #1复制
4 3
2 3 2
1 1
3 2 3 1
4 2 3 1 2
输出 #1复制
1
输入 #2复制
2 5
2 4 2
2 4 2
输出 #2复制
0
输入 #3复制
4 4
1 2
1 3
1 4
1 2
输出 #3复制
-1
说明/提示
Word a_{1},a_{2},…,a_{m}a
1

,a
2

,…,a
m

of length mm is lexicographically not greater than word b_{1},b_{2},…,b_{k}b
1

,b
2

,…,b
k

of length kk , if one of two conditions hold:

at first position ii , such that a_{i}≠b_{i}a
i



=b
i

, the character a_{i}a
i

goes earlier in the alphabet than character b_{i}b
i

, i.e. aa has smaller character in the first position where they differ;
if there is no such position ii and m<=km<=k , i.e. the first word is a prefix of the second or two words are equal.
The sequence of words is said to be sorted in lexicographical order if each word (except the last one) is lexicographically not greater than the next word.

In the first sample, after the round switch is rotated 11 position clockwise the words look as follows:


1 3
2
3 1 2
3 1 2 3
In the second sample, words are already sorted in lexicographical order.

In the last sample, one can check that no shift of the alphabet will work.

思路

设:前一个数列为a[i],后一个为b[j],只要i=j,a[i]>b[j],就要进行+1操作。

同时举一下反例,比如a[i],b[j],i>j,但是前面的元素都是相同的,那么前者的字典序肯定比后者的大,或者还有就是像样例3这样的。

关于这道题的思路,首先我们要明确一点我们无法知道我们要加多少次1,但我们知道我们可以加多少次1,即加多少次1就可以满足前小后大的条件(如果数列的字典序相同,那么我们是可以随便加的)。

例1: i=j,a[i]<b[j],这个情况,我们只要处理安排a[i],使之继续成立即可。

例2: 1-9 a[i]=2 a[j]=5,[1,4]或者[8,9],a[i],b[j]同时加上这些值也是成立。

例3: i=j, a[i]>b[j],我们还是处理啊a[i],使之成立即可,举例说明,1-9 5 2,[5,7],a[i],b[j]同时加上这些值就是成立。

例4: 如果相同,[1,m],无论同时加上这些值中的哪个也都是成立的。但如果出现前面的情况,就不行了。

怎么使得区间修改呢?树状数组,差分方法,[l,r],给从c[l]+1,c[r+1]-1,即可。

我们要注意一点,现在树状数组里的数值不是数列的值,而是记录了修改的次数,两者相似,切莫搞混(相似的原因是数列最多修改m次)。

最后记录一下哪个操作出现了n-1次就是答案(注意树状数组不开下标0,所 以1出现了n-1,代表了0次操作出现n-1次)。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+77,C=1e7+77;
vector<int> words[N];
int cnt[C],n,c;
void calc(int a,int b)
{
    int index = 0;
    while (index < words[a].size() && index < words[b].size())
    {
        if(words[a][index] != words[b][index]) break;
        index++;
    }
    if(index < words[a].size() && index < words[b].size())
    {
        if(words[a][index] < words[b][index])
        {
            cnt[0]++;
            cnt[c - words[b][index] + 1]--;
            cnt[c - words[a][index] + 1]++;
            cnt[c]--;
        }
        else
        {
            cnt[c - words[a][index] + 1]++;
            cnt[c - words[b][index] + 1]--;
        }
    }
    else if(index == words[a].size() && index != words[b].size())
    {
        cnt[0]++;                                   
        cnt[c]--;                                  
    }
    else if(index != words[a].size() && index == words[b].size());
    else
    {
        cnt[0]++;
        cnt[c]--;
    }
}
int main()
{
    scanf("%d%d",&n,&c); 
    for (int i = 1;i <= n;i++)
    {
        int len,w;
        scanf("%d",&len);
        while (len--)
        {
            scanf("%d",&w);
            words[i].push_back(w);
        }
    }
    for (int i = 1;i <= n - 1;i++) calc(i,i + 1);
    bool flag = 0;
    int sum = 0;
    for (int i = 0;i < c;i++)
    {
        sum += cnt[i];
        if(sum == n - 1)
        {
            flag = 1;
            printf("%d",i);
            return 0;
        }
    }
    if(!flag) printf("-1");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值