Codeforces Round #376 (Div. 2) D. 80-th Level Archeology —— 差分法 + 线段扫描法

来源:互联网 发布:淘宝客服每日工作总结 编辑:程序博客网 时间:2024/05/16 04:40

题目链接:http://codeforces.com/contest/731/problem/D


D. 80-th Level Archeology
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 0001 ≤ 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, 1wi, 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 32 3 21 13 2 3 14 2 3 1 2
output
1
input
2 52 4 22 4 2
output
0
input
4 41 21 31 41 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 323 1 23 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.



题意:

给出n个单词(字母的取值范围为1~c),以及一种操作:将每个单词的每个字母+1(如果字母为c,则变为1)。

问:能否经过若干次操作后,这些单词以字典序排列?若能形成字典序,那么操作次数的范围为:0~c-1 , 因为操作c次后又变回原来的值;若不能形成字典序,则输出-1。



题解:

对于上下两个单词的第一次出现字母不相等的位置,为了使其形成升序,有相应的操作次数的区间。

然后每一对单词,都有相应的区间,最后答案就在所有区间的交集上取得(区间用差分法实现)。

线段扫描法:在差分法的基础上,求前缀和,当前缀和刚好等于n-1时(总共有n-1对单词),即表明此处满足每一对单词的取值。



学习之处:

1.选定了某一操作对象,如果很难下手,那么可以更换操作对象

2.差分法 + 线段扫描法 求交集



代码如下:

#include<bits/stdc++.h>using namespace std;typedef long long LL;const double eps = 1e-6;const int INF = 2e9;const LL LNF = 9e18;const int mod = 1e9+7;const int maxn = 1e6+10;vector<int>v[maxn>>1];int range[maxn];int n,c;void init(){    scanf("%d%d",&n,&c);    memset(range,0,sizeof(range));    for(int i = 1; i<=n; i++)        v[i].clear();    for(int i = 1; i<=n; i++)    {        int tot,x;        scanf("%d",&tot);        v[i].push_back(tot);        for(int j = 1; j<=tot; j++)        {            scanf("%d",&x);            v[i].push_back(x);        }    }}void modify(int l, int r)   //差分法{    range[l]++;    range[r+1]--;}int solve(){    for(int i = 2; i<=n; i++)    {        int tot = min(v[i-1][0], v[i][0]);        int j = 1;        while(j<=tot && v[i-1][j]==v[i][j]) j++;        if(j>tot)        {            if(v[i][0]<v[i-1][0])  return -1;            else modify(0, c-1);        }        else        {            int x = v[i-1][j];            int y = v[i][j];            if(x<y) modify(0, c-y), modify(c-x+1, c-1);            else modify(c-x+1, c-y);        }    }        int cnt = 0;    for(int i = 0; i<c; i++)    //线段扫描法    {        cnt += range[i];        if(cnt==n-1)    //(1,2)、(2,3)……(n-1,n),所以总数为n-1            return i;    }    return -1;}int main(){    init();    cout<< solve() <<endl;}





以下是自家学校有关差分法的题目:

18100 奇怪的光照植物

该题有题解

时间限制:500MS  内存限制:65535K
提交次数:547 通过次数:64

题型: 编程题   语言: G++;GCC;VC

Description

一种光照植物,用光照射一天就长1厘米。现在将这种植物种在一条直线型的培养容器中,坐标从0到n-1,每一个整点位置种植一棵这种植物,即共n棵。开始的时候所有植物的高度都为0。实验过程中,进行了m组,每组选择对范围为[L,R]的植物进行光照a天,每组参数L、R、a由输入数据给出。当所有实验结束后,我们想知道所有光照了奇数天的植物总的高度是多少(单位:厘米)。

输入格式

输入第一行包含一个整数T(T<=10),表示有T组测试数据。对每一组测试数据,第一行是两个数n(1<=n<=10^6)和m(0<=m<=10^5),用空格分隔。接下来的m行中每一行包含三个数L,R和a(0<=L<=R<=n-1,0<=a<=100),用空格分隔,表示一个操作。

输出格式

对于每组测试数据输出一行,所有实验操作后所有光照了奇数天的植物总的高度



代码如下:

#include<stdio.h>#include<string.h>#include<stdlib.h>int val[1000050];int main(){    int T,n,l,r,a,m,sum,ans;    scanf("%d",&T);    while(T--)    {        memset(val,0,sizeof(val));        scanf("%d %d",&n,&m);        for(int i = 0;i<m; i++)        {            scanf("%d %d %d",&l,&r,&a);            val[l] += a;            val[r+1] -= a;        }        sum = 0; ans = 0;        for(int i = 0;i<=n+1;i++)        {            sum += val[i];            if(sum%2==1)                ans += sum;        }        printf("%d\n",ans);    }    return 0;}




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