• 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;
    }
     
  • 相关阅读:
    __attribute__((noreturn))的用法
    selenium定位元素的方法
    zzz
    go语言的第一个helloworld
    mac eclipse 创建Java 工程
    Jmeter:图形界面压力测试工具
    使用 HAProxy, PHP, Redis 和 MySQL 轻松构建每周上亿请求Web站点
    从Log4j迁移到LogBack的理由
    SLF4J和Logback日志框架详解
    security with restful
  • 原文地址:https://www.cnblogs.com/jasonlixuetao/p/6086594.html
Copyright © 2020-2023  润新知