zoukankan      html  css  js  c++  java
  • 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 上测试 Redis Cluster的集群填坑笔记
    vmware安装黑苹果教程
    微信支付v3发布到iis时的证书问题
    Linux下安装SQL Server 2016(连接篇SQL Server on linux)
    Linux下安装SQL Server 2016(连接篇SQL Server on linux)
    Linux下安装SQL Server 2016(安装篇SQL Server on linux)
    Linux下安装SQL Server 2016(准备篇SQL Server on linux)
    客服端与服务端APP支付宝支付接口联调的那些坑
    ASP.NET MVC]WebAPI应用支持HTTPS的经验总结
    .net平台下C#socket通信(中)
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/13026448.html
Copyright © 2011-2022 走看看