• 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;
    }
    凡所不能将我击倒的,都将使我更加强大
  • 相关阅读:
    CSS自动控制图片大小的代码
    JS 判断 Radio 单选按钮是否为选中状态 并弹出 值信息
    [转]eclipse github 提交代码
    WEB 开发工具分享
    javaShop的一些总结
    前端进阶试题(css部分)
    如何判断浏览器 然后针对不同的浏览器加入单独的样式
    jquery 提示信息显示后自动消失的具体实现
    html a标签 图片边框和点击后虚线框的有关问题
    html 包含一个公共文件
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/13026448.html
Copyright © 2020-2023  润新知