CF1748E Yet Another Array Counting Problem

Posted tanjunming2020

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1748E Yet Another Array Counting Problem相关的知识,希望对你有一定的参考价值。

CF1748E Yet Another Array Counting Problem

题目大意

对于一个长度为 n n n的序列 x x x,其在区间 [ l , r ] [l,r] [l,r]的最左端最大值位置为满足 l ≤ i ≤ r l\\leq i\\leq r lir x i = max ⁡ j = l r x j x_i=\\max\\limits_j=l^rx_j xi=j=lmaxrxj的最小的整数 i i i

给定两个整数 n , m n,m n,m和一个长度为 n n n的序列 a a a,求满足下列条件的序列 b b b的数量:

  • 序列 b b b的长度为 n n n,且对于任意整数 i ( 1 ≤ i ≤ n ) i(1\\leq i\\leq n) i(1in)都有 1 ≤ b i ≤ m 1\\leq b_i\\leq m 1bim成立
  • 对于任意整数 l , r ( 1 ≤ l ≤ r ≤ n ) l,r(1\\leq l\\leq r\\leq n) l,r(1lrn) a , b a,b a,b在区间的 [ l , r ] [l,r] [l,r]的最左端最大值位置相同

输出满足条件的序列 b b b的数量,对 1 0 9 + 7 10^9+7 109+7取模。

t t t组数据。

数据范围

1 ≤ t ≤ 1 0 3 1\\leq t\\leq 10^3 1t103
2 ≤ n , m ≤ 1 0 5 , ∑ n × m ≤ 1 0 6 2\\leq n,m\\leq 10^5,\\sum n\\times m\\leq 10^6 2n,m105,n×m106
对于所有 i ( 1 ≤ i ≤ n ) i(1\\leq i\\leq n) i(1in),满足 1 ≤ a i ≤ m 1\\leq a_i\\leq m 1aim


题解

首先我们可以想到,对于一个区间 [ l , r ] [l,r] [l,r]和它的最左端最大值位置 x x x,我们可以把这个区间分成 [ l , x − 1 ] [l,x-1] [l,x1] [ x + 1 , r ] [x+1,r] [x+1,r]两个区间来处理。

f ( l , r , x , v ) f(l,r,x,v) f(l,r,x,v)表示区间 [ l , r ] [l,r] [l,r]的最左端最大值位置为 x x x且其值小于等于 v v v时这个区间有多少种放法。那么有

f ( l , r , x , v ) = f ( l , r , x , v − 1 ) + f ( l , x − 1 , v l x , v − 1 ) × f ( x + 1 , r , v r x , v ) f(l,r,x,v)=f(l,r,x,v-1)+f(l,x-1,vl_x,v-1)\\times f(x+1,r,vr_x,v) f(l,r,x,v)=f(l,r,x,v1)+f(l,x1,vlx,v1)×f(x+1,r,vrx,v)

因为一个最左端最大值位置只对应一段区间,且一段区间只有一个最左端最大值位置,所以我们可以用 v l x vl_x vlx表示以 x x x为最左端最大值位置的区间 [ l , r ] [l,r] [l,r] [ l , x − 1 ] [l,x-1] [l,x1]的最左端最大值位置, v r x vr_x vrx表示 [ x + 1 , r ] [x+1,r] [x+1,r]的最左端最大值位置。

因为一开始只有一段区间 [ 1 , n ] [1,n] [1,n],而每次加入一个最左端最大值位置只会多算两个区间,所以总共只会有不超过 2 n + 1 2n+1 2n+1个区间,可以 O ( n log ⁡ n ) O(n\\log n) O(nlogn)将所有 v l x , v r x vl_x,vr_x vlx,vrx计算出来。

然后就是计算 f ( l , r , x , v ) f(l,r,x,v) f(l,r,x,v)了。用记忆化搜索,每个位置只会被计算一次,那么这样的时间复杂度为 O ( n m ) O(nm) O(nm)

总时间复杂度为 O ( ∑ n × m + n log ⁡ n ) O(\\sum n\\times m+n\\log n) O(n×m+nlogn)

code

#include<bits/stdc++.h>
#define lc k<<1
#define rc k<<1|1
using namespace std;
int T,n,m,now,bz,a[200005],v1[200005],v2[200005],tr[1000005],th[1000005];
long long mod=1000000007;
vector<long long>f[200005];
void build(int k,int l,int r)
	if(l==r)
		tr[k]=a[l];th[k]=l;
		return;
	
	int mid=l+r>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	if(tr[lc]>=tr[rc])
		tr[k]=tr[lc];th[k]=th[lc];
	
	else
		tr[k]=tr[rc];th[k]=th[rc];
	

void find(int k,int l,int r,int x,int y)
	if(l>=x&&r<=y)
		if(now<tr[k])
			now=tr[k];bz=th[k];
		
		return;
	
	int mid=l+r>>1;
	if(x<=mid) find(lc,l,mid,x,y);
	if(y>mid) find(rc,mid+1,r,x,y);

int pt(int l,int r)
	if(l>r) return 0;
	now=0;bz=0;
	find(1,1,n,l,r);
	int x=bz;
	v1[x]=pt(l,x-1);v2[x]=pt(x+1,r);
	return x;

long long gt(int l,int r,int x,int v)
	if(l>r||v==0) return 0;
	if(l==r) return v;
	if(f[x][0]) return f[x][v];
	for(int i=1;i<=m;i++)
		long long re=1;
	

CodeForces 863D Yet Another Array Queries Problem 暴力

CodeForces 863D

题意:长度为 n 的数组 a[] ,有两个操作: 1、区间 [l,r] 的数向右移,即 a[i+1] 变为 a[i],a[l] 变为 a[r] 。 2、反转区间 [l,r] 。 最后有 m 个询问 q,输出最后得到的数组里 a[q] 的值。

tags: 一开始觉得是什么数据结构,发现 m <= 100,这样就直接暴力,对于每个询问从后往前反过来操作一遍。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 200005;

int n, q, m, a[N], t[N], l[N], r[N];
int main()
{
    scanf("%d%d%d", &n, &q, &m);
    rep(i,1,n) scanf("%d", &a[i]);
    rep(i,1,q) scanf("%d%d%d", &t[i], &l[i], &r[i]);
    int bi;
    rep(j,1,m)
    {
        scanf("%d", &bi);
        per(i,q,1)
        {
            if(l[i]<=bi && bi<=r[i])
            {
                if(t[i]==1)
                {
                    bi = (bi==l[i]) ? r[i] : bi-1;
                }
                else
                {
                    bi = l[i]+(r[i]-bi);
                }
            }
        }
        printf("%d ", a[bi]);
    }

    return 0;
}

以上是关于CF1748E Yet Another Array Counting Problem的主要内容,如果未能解决你的问题,请参考以下文章

CF-1359 D. Yet Another Yet Another Task ST表+单调队列

CF868F Yet Another Minimization Problem

CF1511C Yet Another Card Deck

CF1511C Yet Another Card Deck

CF1511C Yet Another Card Deck

CF1511C Yet Another Card Deck