[NOI2019]机器人

Posted StaroForgin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NOI2019]机器人相关的知识,希望对你有一定的参考价值。

机器人

题解

首先对于这道题,我们是比较容易得到一个 O ( n 2 B ) O\\left(n^2B\\right) O(n2B) d p dp dp做法的。
我们定义 d p l , r , k dp_l,r,k dpl,r,k表示对于区间 [ l , r ] [l,r] [l,r],其中最大值为 k k k,且机械人不能走出区间 [ l , r ] [l,r] [l,r]的方案数。
其中转移我们可以考虑枚举最后一个大小为 k k k的机械人在哪里,显然,它前面的机械人往后走都是不可能超过它的,它后面的也不可能走到它前面去,这样整个区间就被分成两半了,可以区间 d p dp dp
由于对于任意一个区间,为了满足两边距离差的绝对值不超过 2 2 2,可以放机械人的位置只会有常数个。
只需要再同时维护一个前缀和,就可以 O ( n 2 B ) O\\left(n^2B\\right) O(n2B)了。
但有用的区间真的有 O ( n 2 ) O(n^2) O(n2)吗?题目奇怪的性质好像会使绝大多数区间都不会贡献到答案。
经代码验证,真正有用的区间不会超过 3000 3000 3000个,这样就大大提升了我们代码运行的效率,基本已经可以过前 50 50 50分。

关注之后 A = 1 , B = 1 0 9 A=1,B=10^9 A=1,B=109的部分分。
我们不妨理性猜测这是一个以 [ A , B ] [A,B] [A,B]为值域的多项式,考虑归纳证明。
显然,对于 i = j i=j i=j的情况, d p i , j ( x ) = 1 dp_i,j(x)=1 dpi,j(x)=1
再将它做个前缀和,多项式的前缀和不也是多项式?下面用 d p ′ dp' dp表示做了前缀和了的 d p dp dp
再来看 d p l , r dp_l,r dpl,r的转移式, d p l , r ( x ) = ∑ m i d [ ∣ ( r − m i d ) − ( m i d − l ) ∣ ⩽ 2 ] d p l , m i d − 1 ′ ( x ) d p m i d + 1 , r ′ ( x ) dp_l,r(x)=\\sum_mid[|(r-mid)-(mid-l)|\\leqslant 2]dp'_l,mid-1(x)dp'_mid+1,r(x) dpl,r(x)=mid[(rmid)(midl)2]dpl,mid1(x)dpmid+1,r(x),这不就是把递归到两边的多项式乘起来吗?这不还是一个多项式?
于是我们就完成了证明。
同时通过上面的递归过程,我们可以知道 d p l , r dp_l,r dpl,r是个 r − l r-l rl次的多项式, d p ′ dp' dp自然是 r − l + 1 r-l+1 rl+1次的多项式。
然后就可以拉格朗日插值了。

有了上面的经验,自然可以想到对于之后的点我们将 [ A , B ] [A,B] [A,B]进行离散化,并在离散化后的每个连续区间内, d p l , r dp_l,r dpl,r都是一个多项式。
这是显然的,毕竟在这区间外的位置的答案对里面的贡献都只是一个常数,并不会影响它是不是一个多项式。
那么我们只需要对于离散化后得到的值域区间依次对整个序列区间 d p dp dp求解,并在之后保留下来上一次求解得到的前缀和以辅助下一次 d p dp dp求解,就能够很快地得到整个区间的答案了。
另外,如果插值的时候当前值域区间不足 r − l + 2 r-l+2 rl+2个,我们可以只插值域区间长度这么多的值,毕竟这样就可以应付我们所有的询问了。

m m m为有用区间长度的平方和(显然是比较小的),最后总时间复杂度为 O ( m n ) O\\left(mn\\right) O(mn)

源码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int,int> pii;
#define MAXN 4005
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lowbit(x) (x&-x)
const int mo=1e9+7;
const int inv2=5e8+4;
const int jzm=2333;
const int zero=15;
const LL INF=0x3f3f3f3f3f3f3f3f;
const double Pi=acos(-1.0);
const double eps=1e-9;
const int lim=1000000;
const int orG=3,ivG=332748118;
template<typename _T>
_T Fabs(_T x)return x<0?-x:x;
template<typename _T>
void read(_T &x)
    _T f=1;x=0;char s=getchar();
    while(s<'0'||s>'9')if(s=='-')f=-1;s=getchar();
    while('0'<=s&&s<='9')x=(x<<3)+(x<<1)+(s^48);s=getchar();
    x*=f;

int add(int x,int y,int p)return x+y<p?x+y:x+y-p;
void Add(int &x,int y,int p)x=add(x,y,p);
int qkpow(int a,int s,int p)int t=1;while(s)if(s&1)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1;return t;
int n,a[305],b[305],d[605],totd,ls[MAXN],rs[MAXN];
int g[MAXN][605],id[305][305],idx;pii cp[305];bool vis[MAXN][605];
struct poly
    int m,a[305];poly()m=0;
    void clear()for(int i=0;i<=m;i++)a[i]=0;
    poly operator + (const poly &rhs)const
        poly res;res.m=max(m,rhs.m);res.clear();
        for(int i=0;i<=m;i++)res.a[i]=a[i];
        for(int i=0;i<=rhs.m;i++)Add(res.a[i],rhs.a[i],mo);
        return res;
    
    poly operator * (const int &rhs)const
        poly res;res.m=m;res.clear();
        for(int i=0;i<=m;i++)res.a[i]=1ll*rhs*a[i]%mo;
        return res;
    
    poly operator ^ (const int &rhs)const
        poly res;res.m=m+1;res.clear();
        for(int i=0;i<=m;i++)res.a[i]=mo-1ll*rhs*a[i]%mo;
        for(int i=0;i<=m;i++)Add(res.a[i+1],a[i],mo);
        return res;
    
    int ask(int x)
        int res=0,now=1;
        for(int i=0;i<=m;i++,now=1ll*x*now%mo)
            Add(res,1ll*a[i]*now%mo,mo);
        return res;
    
dp[MAXN],TP;
void init(int l,int r)
    if(id[l][r])return ;
    id[l][r]=++idx;dp[idx].m=dp[idx].a[0]=0;
    if(l==r)return ;int rt=id[l][r];
    for(int i=l;i<=r;i++)
        if(Fabs((i-l)-(r-i))<=2)
            if(l<i)init(l,i-1);
            if(r>i)init(i+1,r);
            if(!ls[rt少儿编程 电子学会机器人等级考试一级真题解析判断题2019-3

机械狗的机器学习入门——菜市场。2019/3/31

少儿编程 电子学会机器人等级考试一级真题解析判断题2019-3

BZOJ 4945 [Noi2017]游戏

LocalMaxima_NOI导刊2009提高

[BZOJ4942][NOI2017]整数(线段树+压位)