题目传送门: http://codeforces.com/contest/731/problem/D
题意: 给n个数串,每个串中元素的最大值为c,现在可以进行如下操作:将所有串的所有元素都加一个数k(0<=k<c-1),使得每个数串都是按照字典序排列的
思路: 只要保证每两个串都符合字典序,则所有串都是有序的。然后每两个串的k都有一个区间,最后取所有k的范围的并集,k的范围可以用线段树来储存
代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <stdio.h>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <vector>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
#define ull unsigned long long
#define mem(n,v) memset(n,v,sizeof(n))
#define MAX 2000005
#define MAXN 2000005
#define PI 3.1415926
#define E 2.718281828459
#define opnin freopen("text.in.txt","r",stdin)
#define opnout freopen("text.out.txt","w",stdout)
#define clsin fclose(stdin)
#define clsout fclose(stdout)
#define haha1 cout << "haha1"<< endl
#define haha2 cout << "haha2"<< endl
#define haha3 cout << "haha3"<< endl
const int INF = 0x3f3f3f3f;
const ll INFF = 0x3f3f3f3f3f3f3f3f;
const double pi = 3.141592653589793;
const double inf = 1e18;
const double eps = 1e-8;
const ll mod = 1e9+7;
const ull mx = 133333331;
int ans = -1;
int vis[MAXN<<2];
struct SegTree
{
bool flag = false;
void build(int l,int r,int rt){
if(l==r){
vis[rt]=1;
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
vis[rt]=1;
}
void update(int L,int R,int l,int r,int rt){
if(L > R)
return;
if(L<=l && r<=R){
// cout << "rt,l,r " << rt << ' ' << l << ' ' << r << endl;
vis[rt] = 0;
return;
}
int m=(l+r)>>1;
if(L<=m) update(L,R,lson);
if(m<R) update(L,R,rson);
}
void query(int L,int R,int l,int r,int rt){
if(!vis[rt]) return;
if(l == r){
if(!flag){
ans = l;
flag = true;
}
}
int m=(l+r)>>1;
if(L<=m) query(L,R,lson);
if(m<R) query(L,R,rson);
}
}tree;
vector<int>a[MAX];
int main()
{
int n,c;
cin >> n >> c;
for(int i=0;i<n;i++) a[i].clear();
int max_len = 0;
for(int i=0;i<n;i++){
int m;
scanf("%d",&m);
int x;
for(int j=1;j<=m;j++){
scanf("%d",&x);
a[i].push_back(x);
}
}
tree.build(1,c,1);
// haha1;
for(int i=1;i<n;i++){
if(a[i] != a[i-1]){
int min_len = 0;
min_len = min(a[i].size(),a[i-1].size());
int j;
for(j=0;j<min_len;j++){
if(a[i][j] < a[i-1][j]){
// cout << "<" << endl;
// cout << "1 " << c-a[i-1][j] << endl;
tree.update(1,c-a[i-1][j],1,c,1);
// cout << c-a[i][j]+1 << ' ' << c << endl;
tree.update(c-a[i][j]+1,c,1,c,1);
break;
}
else if(a[i][j] > a[i-1][j]){
// cout << ">" << endl;
// cout << c-a[i][j]+1 << ' ' << c-a[i-1][j] <<endl;
tree.update(c-a[i][j]+1,c-a[i-1][j],1,c,1);
break;
}
}
if(j == min_len && a[i] < a[i-1]){
cout << "-1" << endl;
return 0;
}
}
}
// for(int i=1;i<=c*2;i++) cout << vis[i] << ' ';
// cout << endl;
tree.query(1,c,1,c,1);
if(ans >= 0){
if(ans == c) cout << "0" << endl;
else cout << ans << endl;;
}
else cout << "-1" <<endl;
return 0;
}