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;
    }
     
  • 相关阅读:
    win10 安装anaconda+tensorflow
    CNN 理论
    mac 调出任何来源方法
    git忽略文件权限检查
    ios plist获取权限
    Vue-从入门到第三次世界大战_1
    libc++abi.dylib: terminating with uncaught exception of type NSException
    unity3d导出xcode项目使用afnetworking 3框架导致_kUTTagClassMIMEType 问题解决方案
    ios cannot use "@throw" with objective-c exceptions disabled 问题解决方案
    关于iOS APP转让
  • 原文地址:https://www.cnblogs.com/jasonlixuetao/p/6086594.html
Copyright © 2011-2022 走看看