CodeForces 731D (差分+线段扫描)

Description

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.

Sample Input

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

给你几个单词,你有一种操作,将所有单词的所有字母+1,当然字母最大号为c,c再加上1就变成1了(就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个交点。

PS:CF的题目质量真高啊!感觉受益匪浅,这个题是我队友教我的,感谢他。我也要努力超过他!

代码如下:

 1 #include <bits/stdc++.h>
 2
 3 using namespace std;
 4 vector <int> words[500010];
 5 int cnt[1000010],n,c;//cnt表示转几次是否满足要求
 6 void calc (int a,int b)
 7 {
 8     int idx=0;//idx表示失配位置
 9     while (idx<words[a].size()&&idx<words[b].size())
10     {
11         if (words[a][idx]!=words[b][idx])
12             break;
13         idx++;
14     }
15     if (idx<words[a].size()&&idx<words[b].size())//失配的位置在a,b的中部
16     {
17         if (words[a][idx]<words[b][idx])//在失配位置是b的大于a的
18         {
19             cnt[0]++;
20             cnt[c-words[b][idx]+1]--;
21             cnt[c+1-words[a][idx]]++;
22             cnt[c]--;
23         }
24         else
25         {
26             cnt[c+1-words[a][idx]]++;
27             cnt[c-words[b][idx]+1]--;
28         }
29     }
30     else if (idx==words[a].size()&&idx!=words[b].size())//a比b短
31     {
32         cnt[0]++;                                   //a 123
33         cnt[c]--;                                   //b 123456
34     }
35     else if (idx!=words[a].size()&&idx==words[b].size())//a比b长
36                                                     //a 12345
37                                                     //b 123
38     ;
39     else //a和b完全一样
40     {
41         cnt[0]++;
42         cnt[c]--;
43     }
44 }
45 int main()
46 {
47     //freopen("de.txt","r",stdin);
48     while (~scanf("%d%d",&n,&c))
49     {
50         memset(cnt,0,sizeof cnt);
51         for (int i=0;i<500010;++i)
52         words[i].clear();
53         for (int i=0;i<n;++i)
54         {
55             int len,w;
56             scanf("%d",&len);
57             while (len--)
58             {
59                 scanf("%d",&w);
60                 words[i].push_back(w);
61             }
62         }
63         for (int i=0;i<n-1;++i)
64         calc(i,i+1);
65         bool ok=false;
66         int sum=0;
67         for (int i=0;i<c;++i)
68         {
69             sum+=cnt[i];
70             if (sum==n-1)
71             {
72                 ok=true;
73                 printf("%d\n",i);
74                 break;
75             }
76         }
77         if (!ok)
78         printf("-1\n");
79     }
80     return 0;
81 }
时间: 2024-10-25 05:59:00

CodeForces 731D (差分+线段扫描)的相关文章

G - Greg and Array CodeForces - 296C 差分+线段树

题目大意:输入n,m,k.n个数,m个区间更新标记为1~m.n次操作,每次操作有两个数x,y表示执行第x~y个区间更新. 题解:通过差分来表示某个区间更新操作执行的次数.然后用线段树来更新区间. #include<bits/stdc++.h> using namespace std; const int N=1E5+7; typedef long long ll; ll arr[N]; ll tt[N],cnt[N]; struct stu{ ll value,add; }tree[N+N+N

CodeForces 46DParking Lot线段树

#include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #include <set> #include <qu

Codeforces 19D Points 线段树+set

题目链接:点击打开链接 线段树维护y值大于val的最小x值 #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <iostream> #include <map> #include <set> #include <math.h> using namespace std; #define inf

Codeforces 444C(线段树)

区间颜色不一致就更新到底,否则lazy标记 #include<cstdio> #include<cstring> #include<cmath> #include<queue> using namespace std; #define lc l,m,index<<1 #define rc m+1,r,index<<1|1 #define N 100005 #define ll __int64 struct node { bool sa

APIO 2012 守卫 | 差分 / 线段树 + 贪心

题目:luogu 3634 首先把为 0 的区间删去,重新标号,可以差分也可以线段树. 把包含其他线段的线段删去,原因 1 是它没有用,原因 2 下面再说.然后,贪心选取最少的点来满足所有线段,即选取还没有点在上面的线段的右端点.如下图中选取的红色方格. 倘若不删去包含其他线段的线段,如上图中的蓝色虚线,我们在贪心选取点的时候,就会先扫到蓝线的左端点而后扫到第二条红线,按照规则,我们会选择蓝线的右端点 6 号点,接下来扫到第二条红线时,由于它上面并没有点被选取,所以又会选取它的右端点 5 号点,

[LuoguP1438]无聊的数列(差分+线段树/树状数组)

\(Link\) \(\mathcal{Description}\) 给你一个数列,要求支持单点查询\(and\)区间加等差数列. \(\mathcal{Solution}\) 哈哈哈哈这个题十分的有意思,至于为什么有意思等会儿再说~ 其实我们观察这两个操作,单点查询--就是那个\(naive\)的单点查询,那么区间加等差数列呢?我们可以思考一下等差数列的性质--存在公差.不妨考虑差分 \(emmm\)发现我好像还没有在博客园里提过差分--那么就整一整吧正好我好久没捯饬这玩意儿了\(qwq\)

[树上差分][线段树合并]JZOJ 3397 雨天的尾巴

Description 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连 根拔起,以及田地里的粮食被弄得一片狼藉. 无奈的深绘里和村民们只好等待救济粮来维生. 不过救济粮的发放方式很特别. 首先村落里的一共有n 座房屋,并形成一个树状结构.然后救济粮分m 次发放,每次选择 两个房屋(x,y),然后对于x 到y 的路径上(含x 和y) 每座房子里发放一袋z 类型的救济粮.

New Year and Old Subsequence CodeForces - 750E(线段树 + 矩阵)

New Year and Old Subsequence (CodeForces - 750E) 题意: 给出一个长度为\(N\)的数字串,\(q\)次询问.每次询问一段区间.在区间内删除尽量少的字符,使得区间内含有序列"\(2017\)",且不含有"\(2016\)". \(n,q<=200000\). 题解: 用\(01234\)五种状态分别表示"". "\(2\)"."\(20\)"."

Sum Queries? CodeForces - 1217E (线段树)

Sum Queries? CodeForces - 1217E (线段树) 题意: 定义一个集合为\(balanced\)的,当且仅当集合内数字之和的每个十进制位,都与集合中某个数该位相同.否则,称该集合为\(unbalanced\)的. 给定一个长度为\(n\)的序列,\(q\)次询问一个区间内数字之和最小的\(unbalanced\)集合,输出数字之和.若没有输出\(-1\). \(n,q<=200000\). 题解: 可以发现,如果存在\(unbalanced\)集合,那么最小的一定是只两