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;
    }
     
  • 相关阅读:
    nagios安装配置
    Nagios:企业级系统监控方案
    使用Maven搭建Struts2+Spring3+Hibernate4的整合开发环境
    SecureCRT最佳配色方法+直接修改默认配置方法
    highcharts插件使用总结和开发中遇到的问题及解决办法
    关于Highcharts图表组件动态修改属性的方法(API)总结之Series
    Linux中环境变量文件及配置
    使用正则表达式匹配任意字符包括空格和换行符
    设置mysql远程连接root权限
    java读取文件夹下所有文件并替换文件每一行中指定的字符串
  • 原文地址:https://www.cnblogs.com/jasonlixuetao/p/6086594.html
Copyright © 2011-2022 走看看