1 条题解
-
0
没人搬官方题解,来搬一波,感觉这题还是比较妙的。
考虑每个位置在这个“DP Table”上的转移形成的路径,然后转而考虑有多少个位置的路径会经过形如
(a,b)->(a,b-1)这个转移。考虑所有满足 的 组成的区域 (官方题解称之为 ),那么考虑观察一个点 ,当然要满足 ,它的转移路径一定会有一步是从 内跨到 外,那么考虑这一步是向下( 减去 )还是向左( 减去 )。
设 表示 数组下标在 的所有元素的最小值, 同理,那么 会向左离开 当且仅当满足 ,证明显然, 的最小值的位置会干掉所有 的对应位置。
但从左边离开也不代表就一定走的是
$$\sum\limits_{c=a}^n\sum\limits_{d=b}^n[\min A[a,c] < \min B[b,d]] - \sum\limits_{c=a+1}^n\sum\limits_{d=b}^n[\min A[a+1,c] < \min B[b,d]]$$(a,b)->(a,b-1),所以要求出这个还需要减去从左边离开 为左下角的区域的方案数,所以它被经过的方案数就是然后再乘上系数 即可。
发现两部分是类似的,那么可以给系数 做处理,给每个 同时进行 即可,然后可以得到所有向左的转移的带权和就是
$$\sum\limits_{a=1}^n\sum\limits_{b=1}^n\sum\limits_{c=a}^n\sum\limits_{d=b}^nX_a[\min A[a,c] < \min B[b,d]]$$同理可以计算出向下转移的带权和。
发现上面的式子其实只比较两个 的大小关系,那么可以处理出 $F_{A.i} = \sum\limits_{l=1}^n\sum\limits_{r=l}^n[\min A[l,r]==i]$,$G_{A.i} = \sum\limits_{l=1}^n\sum\limits_{r=l}^nX_l[\min A[l,r]==i]$, 同理。
那么答案就是
$$\sum\limits_{i=1}^{2n}\sum\limits_{j=i+1}^{2n}G_{A,i}F_{B,j} + G_{B,i}F_{A,j}$$可以用各种方法求出,如笛卡尔树等,我用的是从大到小插入值然后并查集合并信息的思路。
代码
#include<cstdio> #define TY int #define MAXN 250002 #define MAXM 500002 #define debug if( 1 &&putchar('>')) #define FOR(i,a,b) for(TY i=(a);i<=(b);i=-~i) #define fOR(i,a,b) for(TY i=(a);i<(b);i=-~i) #define ROF(i,a,b) for(TY i=(a);i>=(b);i=~-i) #define rOF(i,a,b) for(TY i=(a);i>(b);i=~-i) #define EDG(i,u) for(TY i=hed[u];i;i=nxt[i]) using namespace std; typedef long long ll; const TY M=998244353; typedef unsigned long long ull; TY _abs(TY a){return a<0?-a:a;} TY maxn(TY a,TY b){return a>b?a:b;} TY minn(TY a,TY b){return a<b?a:b;} inline void updmx(TY &x,TY y){if(x<y)x=y;} inline void updmn(TY &x,TY y){if(x>y)x=y;} inline void add(TY &x,TY y){if((x+=y)>=M)x-=M;} TY gcd(TY a,TY b){return b?gcd(b,a%b):a;} TY qp(TY a,TY b){TY ans=1;do{if(1&b)ans=ans*a%M;a=a*a%M;}while(b>>=1);return ans;} char getc(){char ch=getchar();while(ch==' '||ch=='\n'||ch=='\r')ch=getchar();return ch;} TY qr(){ char ch=getchar();TY s=0,x=1; for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')x=-1; for(;ch>='0'&&ch<='9';ch=getchar())s=s*10+ch-'0';return x*s; }void qw(TY a){if(a>9)qw(a/10);putchar(a%10+'0');} void qw(TY a,char ch){ if(a<0){a=-a;putchar('-');} if(a>9)qw(a/10);putchar(a%10+'0'); if(ch)putchar(ch); }TY n=qr(),m,a[MAXN],b[MAXN],x[MAXN],y[MAXN],ps[MAXM],u,p,q; TY fa[MAXN],sz[MAXN],sm[MAXN],nma[MAXM],sma[MAXM],nmb[MAXM],smb[MAXM],ans; TY getfa(TY u){return fa[u]!=u?fa[u]=getfa(fa[u]):u;} //代码中nma=FA,nmb=FB,sma=GA,smb=GB int main(){ FOR(i,1,n)a[i]=qr();FOR(i,1,n)b[i]=qr(); FOR(i,1,n)x[i]=qr();FOR(i,1,n)y[i]=qr(); ROF(i,n,2){add(x[i],M-x[i-1]);add(y[i],M-y[i-1]);} ans=1ll*((M<<1)-x[1])*n%M*n%M;//先去掉从(1,1)向左转移的贡献 m=n<<1;FOR(i,1,n)ps[a[i]]=i; ROF(i,m,1)if(u=ps[i]){ sm[fa[u]=u]=x[u];sz[u]=1;p=q=0; if(fa[u-1])fa[p=getfa(u-1)]=u; if(fa[u+1])fa[q=getfa(u+1)]=u; add(sm[u],sm[p]);add(sm[u],sm[q]);sz[u]+=sz[p]+sz[q]; add(sma[i],1ll*(sm[p]+x[u])*(sz[q]+1)%M); add(nma[i],1ll*(sz[p]+1)*(sz[q]+1)%M); }FOR(i,1,m)ps[i]=0; FOR(i,1,n)fa[ps[b[i]]=i]=0; ROF(i,m,1)if(u=ps[i]){ sm[fa[u]=u]=y[u];sz[u]=1;p=q=0; if(fa[u-1])fa[p=getfa(u-1)]=u; if(fa[u+1])fa[q=getfa(u+1)]=u; add(sm[u],sm[p]);add(sm[u],sm[q]);sz[u]+=sz[p]+sz[q]; add(smb[i],1ll*(sm[p]+y[u])*(sz[q]+1)%M); add(nmb[i],1ll*(sz[p]+1)*(sz[q]+1)%M); }ROF(i,m-1,1){ add(nma[i],nma[i+1]); add(nmb[i],nmb[i+1]); }FOR(i,1,m){ add(ans,1ll*sma[i]*nmb[i+1]%M); add(ans,1ll*smb[i]*nma[i+1]%M); }qw(ans);return 0; }
- 1
信息
- ID
- 11521
- 时间
- 2000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者