zoukankan      html  css  js  c++  java
  • 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;
    }
     
  • 相关阅读:
    js----定义变量的几种方式
    Vue----项目增加百度统计
    Vuex----核心概念和API
    Vuex----理解
    回到学校,国庆收假的第一天
    再次回到武汉
    收获的季节,最忙其实也是最没有收获的时光
    虚无缥缈的自信,一落千丈的打击
    愤怒、愤怒,终于适应了奔波
    总是骗人的你
  • 原文地址:https://www.cnblogs.com/jasonlixuetao/p/6086594.html
Copyright © 2011-2022 走看看