codeforces_731D_(前缀和)(树状数组)

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 inlexicographical 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

题意:n个单词,c个字母,每一次操作都会使所有单词的所有字母变为它字典序的后一个字母。当所有单词按字典序从小到大排列时,
完成任务,问需要多少此操作。

思路:每两个单词成为字典序,都有一个操作次数的区间,一次枚举相邻的两个单词,求得n-1个区间,在这n-1个区间的交集中的数便满足要求。

前缀和:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define N 500005
#define C 1000005
vector<int> v[N];
int seg[C];
int main()
{
    int n,c;
    scanf("%d%d",&n,&c);
    for(int i=0; i<n; i++)
    {
        int nn;
        scanf("%d",&nn);
        for(int j=0; j<nn; j++)
        {
            int num;
            scanf("%d",&num);
            v[i].push_back(num);
        }
        }
        int ok=1;
        for(int i=0; i<n-1; i++)
        {
            int p=0;
            while(1)
            {
                if(p==v[i].size())
                {
                    seg[0]+=1;
                    seg[c+1]-=1;
                    break;
                }
                else if(p==v[i+1].size())
                {
                    ok=0;
                    break;
                }
                else if(v[i+1][p]!=v[i][p])
                {
                    if(v[i+1][p]<v[i][p])
                    {
                        seg[c-v[i+1][p]+1]-=1;
                        seg[c-v[i][p]+1]+=1;
                    }
                    else if(v[i+1][p]>v[i][p])
                    {
                        seg[0]+=1;
                        seg[c-v[i+1][p]+1]-=1;
                        seg[c-v[i][p]+1]+=1;
                        seg[c]-=1;
                    }
                    break;
                }
                p++;
            }
        }
        if(!ok)
            printf("-1
");
        else
        {
            int pre=0,res=-1;
            for(int i=0; i<=c; i++)
            {
                pre+=seg[i];
                //cout<<pre<<endl;
                if(pre==n-1)
                {
                    res=i;
                    break;
                }
            }
            printf("%d
",res);
        }
    return 0;
}


树状数组:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
#define N 500005
#define C 1000005

vector<int> v[N];
int n,c,s[C];

int lowbit(int x)
{
    return x&(-x);
}


void add(int k,int x)
{
    for(int i=k; i<=c; i+=lowbit(i))
        s[i]+=x;
}

int Sum(int k)
{
    int res=0;
    for(int i=k; i>0; i-=lowbit(i))
        res+=s[i];
    return res;
}


int main()
{
    while(scanf("%d%d",&n,&c)!=EOF)
    {
        memset(s,0,sizeof(s));
        for(int i=0; i<=n; i++)
            v[i].clear();
        for(int i=0; i<n; i++)
        {
            int nn;
            scanf("%d",&nn);
            for(int j=0; j<nn; j++)
            {
                int num;
                scanf("%d",&num);
                v[i].push_back(num);
            }
        }
        int ok=1;
        for(int i=0; i<n-1; i++)
        {
            int p=0;
            while(1)
            {
                if(p==v[i].size())
                {
                    add(1,1);
                    break;
                }
                else if(p==v[i+1].size())
                {
                    ok=-1;
                    break;
                }
                else if(p<v[i+1].size()&&p>=v[i].size())
                {
                    add(1,1);
                    break;
                }
                else if(v[i][p]!=v[i+1][p])
                {
                    if(v[i][p]>v[i+1][p])
                    {
                        add(c-v[i][p]+2,1);
                        add(c-v[i+1][p]+2,-1);
                    }
                    else if(v[i][p]<v[i+1][p])
                    {
                        add(1,1);
                        add(c-v[i+1][p]+2,-1);
                        add(c-v[i][p]+2,1);
                        add(c+1,-1);
                    }
                    break;
                }
                p++;
            }
        }
        if(!ok)
            printf("-1
");
        else
        {
            int res=-1;
            for(int i=1; i<=c+1; i++)
                if(Sum(i)==n-1)
                {
                    res=i-1;
                    break;
                }
            printf("%d
",res);
        }
    }
    return 0;
}
 
原文地址:https://www.cnblogs.com/jasonlixuetao/p/6086594.html