• Codeforces 213E Two Permutations


    题目链接

    https://codeforces.com/contest/213/problem/E

    题目大意

    给你一个 1 ~ N的排列 A 和一个 1 ~ M 的排列 B ( N <= M )

    问有多少个 d 可以使得排列 A 的每个数 + d 后为排列 B 的子序列

    解题思路

    权值线段树 + hash

    只要满足每个 a[i] + d 在 A 中的相对位置和在 B 中的相对位置相同即可

    也就是判断 B 中[1~N]、[2~N+1] ... [M - N + 1~ M]与A中[1, N] 的相对位置是否相同

    于是我们先可以定义 pos[i] 表示 i 这个数在 B 中的位置(pos[ b[ i ] ] = i)

    要判断相对位置是否相同,我们可以通过 hash 来操作

    具体是用线段树维护 1 ~ M 的区间, 第i个区间表示 B 数组第i个位置的数是多少

    然后简单来说就是再把这些位置的值提取出来计算hash值是否会和A的hash值相同

    (细节看代码)

    AC_Coder

    #include<bits/stdc++.h>
    #define rep(i,a,n) for (int i=a;i<=n;i++)
    #define int long long
    #define ull unsigned long long
    using namespace std; 
    const int N = 2e5 + 10;
    const int P = 13331;
    const int mod = 999998639;
    ull power[N];
    int a[N] , b[N] , pos[N];
    struct Seg_ment{
        ull pre , tot;
        int l , r;
    }tree[N << 2];
    void push_up(int id)
    {
        tree[id].tot = tree[id << 1].tot + tree[id << 1 | 1].tot;
        tree[id].pre = (tree[id << 1].pre * power[tree[id << 1 | 1].tot] + tree[id << 1 | 1].pre) % mod;    
    }
    void build(int l , int r , int id)
    {
        tree[id].l = l , tree[id].r = r;
        tree[id].pre = 0;
        if(l == r)
            return ;
        int mid = l + r >> 1;
        build(l , mid , id << 1);
        build(mid + 1 , r , id << 1 | 1);
        push_up(id);
    }
    void update(int id , int pos , int val)
    {
        if(tree[id].l == tree[id].r)
        {
            if(!val) tree[id].tot -= 1;
            else tree[id].tot += 1;
            tree[id].pre = val;
            return ;        
        }
        int mid = tree[id].l + tree[id].r >> 1;
        if(pos <= mid) update(id << 1 , pos , val);
        if(pos > mid)  update(id << 1 | 1 , pos , val);
        push_up(id);
    }
    void init()
    {
        power[0] = 1;
        rep(i , 1 , 200000)
        power[i] = power[i - 1] * P % mod;
    }
    signed main()
    {
        init();
        int n , m , ans = 0;
        cin >> n >> m;
        build(1 , m , 1);
        ull sum = 0 , add = 0;
        rep(i , 1 , n)
            cin >> a[i] , sum = (sum * P + a[i]) % mod , add += power[i - 1] , add %= mod;
        rep(i , 1 , m)
            cin >> b[i] , pos[b[i]] = i;
        rep(i , 1 , m)
        {
            if(i > n) update(1 , pos[i - n] , 0);
            update(1 , pos[i] , i);
            int cha = i - n;
            if(cha >= 0 && tree[1].pre % mod == (sum + cha * add) % mod) ans ++ ;
        }
        cout << ans << '
    ';
        return 0;
    }
    凡所不能将我击倒的,都将使我更加强大
  • 相关阅读:
    windows 将常用程序添加到右键菜单中去
    用MediaPlayer播放assets中的音乐文件出现的问题
    android开发技巧
    windows下如何安装java6.0
    ubuntu下运行windows程序wine
    ubuntu系统备份与恢复
    Mongo北京大会3月3号召开!报名抢注火爆进行中!(免费)
    《人月神话》作者Frederick P. Brooks, Jr.大师论设计原本
    HTML 5:富媒体时代的Web内容新规范
    2011年3月华章新书书讯:ASP.NET本质论、Erlang编程指南、SNS网站构建
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/13026448.html
Copyright © 2020-2023  润新知