您的位置:首页 > 其它

codeforces 731 D 80-th Level Archeology (差分+线段扫描)

2016-11-20 15:10 471 查看
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
n 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
x (1 ≤ x ≤ c - 1) is replaced with hieroglyph
(x + 1), and hieroglyph
c is replaced with hieroglyph 1.

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.

Input
The first line of the input contains two integers n and
c (2 ≤ n ≤ 500 000,
1 ≤ c ≤ 106) — the number of words, written on the lock, and the number of different hieroglyphs.

Each of the following n lines contains the description of one word. The
i-th of these lines starts with integer
li (1 ≤ li ≤ 500 000), that denotes the length of the
i-th word, followed by
li integers
wi, 1,
wi, 2, ...,
wi, li (1 ≤ wi, j ≤ c) — the indices of hieroglyphs that
make up the i-th word. Hieroglyph with index
1 is the smallest in the alphabet and with index
c — the biggest.

It's guaranteed, that the total length of all words doesn't exceed
106.

Output
If it is possible to open the door by rotating the round switch, print integer
x (0 ≤ x ≤ c - 1) that defines the required number of clockwise rotations. If there are several valid
x, print any of them.

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

Examples

Input
4 3
2 3 2
1 1
3 2 3 1
4 2 3 1 2


Output
1


Input
2 5
2 4 2
2 4 2


Output
0


Input
4 4
1 2
1 3
1 4
1 2


Output
-1


Note
Word a1, a2, ..., am of length
m is lexicographically not greater than word
b1, b2, ..., bk of length
k, if one of two conditions hold:

at first position i, such that
ai ≠ bi, the character
ai goes earlier in the alphabet than character
bi, i.e.
a has smaller character in the first position where they differ;

if there is no such position i and
m ≤ 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
1 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.

题意:给你几个单词,你有一种操作,将所有单词的所有字母+1,当然字母最大号为c,c再加上1就变成1了(就1~c轮着转)。问你最少操作几次使得所有的单词满足字典序?如果根本不能满足输出-1。

解题思路:一开始一点思路都没有,连突破口在哪都不知道,姿势上来就错,我一开始想的是处理n个单词的第一个字母,第二个字母,...第n个字母 满足字典序,

然而这种错误的思路一点头绪都没有,后来去找题解,原来解题思路是暴力两两比较单词,每个单词都有一个变动的区间,这个变动区间满足单词变动之后满足字典序,

这里要注意,如果本来就满足的话,变动区间可以在【0,c-1】,这边需要分类讨论一下,巴拉巴拉....

之后找到这些区间的交集中,是否满足有c-1个交点,这里就要用到差分的思想!!!!

1.首先介绍下什么是差分法。比如给你一个长度为n的数组cnt,一开始全是0。现在如果让你从下标2~4的位置都+1,怎么做?cnt[2]++,cnt[5]--

数组变成了0 0 1 0 0 -1 0....,我们再进行for(int i=0;i<n;++i)cnt[i]+=cnt[i-1];  现在变成了0 0 1 1 1 0 0...是不是2~4都+1了?

总结一下,差分的想法就是在区间a~b中+1,等价于cnt[a]++,cnt[b+1]--,然后再处理一边前缀和就行了。

2.什么是线段扫描法?给你n个区间,问你有没有一个公共的区间是这所有n个区间的公共子区间。

首先把这几个区级排好,然后找一条竖着的直线,从左向右平移,然后看有没有一瞬间这个直线与所有区间都相交,及有n个交点。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 1e6+100;
vector<int>a
;
int d
;

void work(int l,int r)
{
d[l]++;
d[r+1]--;
}

int main()
{
ios::sync_with_stdio(false);
int n,c,i,j,temp;
int x,y;
cin>>n>>c;
for(i=1;i<=n;i++) {
cin>>temp;
a[i].push_back(temp);
for(j=1;j<=a[i][0];j++) {
cin>>temp;
a[i].push_back(temp);
}
}
for(i=1;i<n;i++) {
int len=min(a[i][0],a[i+1][0]);
for(j=1;j<=len;j++) {
x=a[i][j];
y=a[i+1][j];
if(x!=y) break;
}
if(j>len && a[i][0]>a[i+1][0]) {
cout<<"-1"<<endl;
return 0;
}
if(x!=y) {
if(x<y) {
work(0,c-y);
work(c+1-x,c-1);
}
else if(x>y) work(c+1-x,c-y);
}
else work(0,c-1);
}
int sum=0;
for(i=0;i<c;i++) {
sum+=d[i];
if(sum==n-1) {
cout<<i<<endl;
return 0;
}
}
cout<<"-1"<<endl;
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: