11.8 mx
t1


说人话就是你可以把 \(a\) 的一个长为 \(m\) 的子区间替换成把 \(b\) 序列视作一个环,以 \(b\) 任意元素开头的长为 \(m\) 的区间。
特判 \(m=1\)。
然后显然把 \(b\) 序列调整成字典序最小最优。
然后如果 \(a\) 序列有一个子区间被替换了,由于 \(b\) 序列元素不同,所以 \(a\) 序列之后的位置也必须被替换,相当于 \([i,n-m]\) 这些位置均被赋值为 \(b_1\),然后最后一个子区间赋值为 \(b\);
特判只更换最后一个子区间更优的情况。
思想:其实可以先考虑贪心,每个位置能换就换,时间复杂度 \(O(nm)\)。然后发掘性质 + 一点分讨。其实就是贪心()
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <algorithm>
#define FOR(i,a,b) for(int i = (a);i <= (b);++i)
#define REP(i,a,b) for(int i = (a);i >= (b);--i)
static char stkk[200];
template<typename T>inline void output(T x){
if(!x)return putchar('0'),void();
if(x<0)x = ~x+1,putchar('-');
int top = 0;
for(;x;stkk[++top]=x%10^48,x/=10);
for(;top;putchar(stkk[top--]));
}
template<typename T>inline void readx(T &x){
x = 0;int y = 1;char c = getchar();
for(;c<48||c>58;c = getchar())if(c=='-')y = -1;
for(;c>=48&&c<=58;c = getchar())x = (x<<1)+(x<<3)+(c^48);
x *= y;
}
const int N = 2e6+10,nf = 1e9+10;
static int a[N],b[N],c[N],n,m;
inline void solve(){
readx(n),readx(m);
FOR(i,1,n)readx(a[i]);
int tmp = nf,id;
FOR(i,1,m)readx(c[i]),tmp = std::min(tmp,c[i]);
if(m==1){
FOR(i,1,n)a[i] = std::min(a[i],c[1]);
goto yes;
}
FOR(i,1,m)if(c[i]==tmp){
id = i;
break;
}
FOR(i,1,m)b[i] = c[(i+id-2+m)%m+1];
// puts("b:");FOR(i,1,m)output(b[i]),putchar(' ');putchar(10);
FOR(i,1,n-m+1){
if(a[i]>tmp){
FOR(j,i,n-m)a[j] = tmp;
FOR(j,1,m)a[n-m+j] = b[j];
goto yes;
}
}
FOR(j,1,m){
if(a[n-m+j]^b[j]){
if(a[n-m+j]>b[j]){
FOR(j,1,m)a[n-m+j] = b[j];
goto yes;
}
goto yes;
}
}
yes:
FOR(i,1,n)output(a[i]),putchar(' ');putchar(10);
}
signed main(){
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
int t;for(readx(t);t--;solve());
return 0;
}
t2


考虑生成最小生成树的过程,肯定先考虑为 \(0\) 的边,注意到如果 \(0\) 边联通的点在原图中的诱导子图非树,那么剩余的边无法判断;否则你剩余为 \(1\) 的边都能被判断出来,剩余的边自然就是 \(0\) 了。
所以可以先把所有边的变成 \(1\);直接状压,每次加入进来一个点集,满足诱导子图是一个树,并且所有树边为 \(0\)(钦定 \lowbit S 在加入点集中即可)。上述可以状压预处理。
总时间复杂度 \(O(T3^n)\)。
思想:生成 MST 小边会阻断大边,大边就没用了;
这题如果存在 \(1\) 边被 \(0\) 边阻断必然不合法;反之合法。
像 这题 非 lct 做法中,你下传边时,如果钦定动态边为大边,未被加入的静态边必然被其它静态边阻断,可以丢掉;如果钦定动态边为小边,那么仍存在的静态边就必然不会被任何边阻断,可以直接缩点。
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#define FOR(i,a,b) for(int i = (a);i <= (b);++i)
#define REP(i,a,b) for(int i = (a);i >= (b);--i)
static char stkk[200];
template<typename T>inline void output(T x){
if(!x)return putchar('0'),void();
if(x<0)x = ~x+1,putchar('-');
int top = 0;
for(;x;stkk[++top]=x%10^48,x/=10);
for(;top;putchar(stkk[top--]));
}
template<typename T>inline void readx(T &x){
x = 0;int y = 1;char c = getchar();
for(;c<48||c>58;c = getchar())if(c=='-')y = -1;
for(;c>=48&&c<=58;c = getchar())x = (x<<1)+(x<<3)+(c^48);
x *= y;
}
const int N = 16,M = 1<<16,nf = 1e9+10;
struct work1{
int f[M],dp[M],w[N][N][2],e[N];
int pw[N],lg[M],n,m,mxn;
inline void init_pw(int n){
pw[0] = 1;
FOR(i,1,n)lg[pw[i]=pw[i-1]<<1] = i;
}
inline void add(int x,int y,bool flg){
e[x]|=pw[y-1],e[y]|=pw[x-1];
++w[x][y][flg],++w[y][x][flg];
}
inline void ckmax(int &x,int y){
x<y&&(x=y);
}
inline void get_dp(){
// f
FOR(i,0,mxn)dp[i] = f[i] = -nf;
FOR(i,0,n-1)dp[pw[i]] = f[pw[i]] = 0;
dp[0] = f[0] = 0;
FOR(S,1,mxn){
for(int j = S,x,T,y;j;j&=j-1){
x = lg[j&-j]+1,T = S^(j&-j),y = lg[e[x]&T]+1;
if(__builtin_popcount(e[x]&T)==1&&w[x][y][0]+w[x][y][1]==1)ckmax(f[S],f[T]+w[x][y][0]);
}
}
FOR(S,1,mxn){
ckmax(dp[S],f[S]);
for(int T = S&(S-1);T;T = (T-1)&S)ckmax(dp[S],dp[T]+f[S^T]);
}
}
inline void solve(){
readx(n),readx(m);
mxn = pw[n]-1;
//init
FOR(i,1,n)e[i] = 0;
FOR(i,1,n)FOR(j,1,n)w[i][j][0] = w[i][j][1] = 0;
int tx,ty,tw,ans = 0;bool flg = 1;
FOR(i,1,m){
readx(tx),readx(ty),readx(tw);
if(tx==ty)flg &= 0;
add(tx,ty,tw);
if(!tw)++ans;
}
if(!flg)return puts("-1"),void();
get_dp();
output(ans-dp[mxn]),putchar(10);
}
void main(){
init_pw(N-1);
int t;for(readx(t);t--;solve());
}
}A;
signed main(){
freopen("rights.in","r",stdin);
freopen("rights.out","w",stdout);
A.main();
return 0;
}
编码错误:忘记如何枚举子集;x&-x 不代表最后一位的元素,而是整个二进制数;
发现 状压dp 已经不熟了,需要紧急加训。
t3


两点最小距离以及方案数可以预处理,记前者为 \(f_{i,j}\),后者为 \(g_{i,j}\)。
直接旅行商问题。定义 \(dp0_{S,j},dp1_{S,j}\) 表示走过了 \(S\) 点集,现在在 \(j\) 这个点的最短路和方案数。转移是容易的。
然后就挂没了(),考虑如果从 \(i\) 到 \(j\) 的最短路径中存在一条经过 \(z\) 的,那么会重复计数。
定义 \(t_{S,i,j}\) 表示从 \(i\) 到 \(j\) 不经过别的点(不包括在 \(S\) 点集的点)的方案数。
有 \(to_{S,i,j} = g_{i,j}-\sum_{z}[d_{i,z}+d_{z,j}=d_{i,j}]to_{S,i,z}g_{z,j}\),意义是枚举第一个重复的点 \(z\) 减掉。
转移可以按 \(d_{x,y}\) 从小到大转移。
时间复杂度 \(O(m^32^m)\),注意到好像过不了,但是 std 就是这个复杂度()。
总结:状压时要考虑是否会算重,这很重要!比如是否有重复的点;或者像这题,它的点不是图上孤立的。
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <cstring>
#define FOR(i,a,b) for(int i = (a);i <= (b);++i)
#define REP(i,a,b) for(int i = (a);i >= (b);--i)
static char stkk[200];
template<typename T>inline void output(T x){
if(!x)return putchar('0'),void();
if(x<0)x = ~x+1,putchar('-');
int top = 0;
for(;x;stkk[++top]=x%10^48,x/=10);
for(;top;putchar(stkk[top--]));
}
template<typename T>inline void readx(T &x){
x = 0;int y = 1;char c = getchar();
for(;c<48||c>58;c = getchar())if(c=='-')y = -1;
for(;c>=48&&c<=58;c = getchar())x = (x<<1)+(x<<3)+(c^48);
x *= y;
}
const int N = 17,M = (1<<16)+1,G = 3.6e6+10,mo = 998442353,nf = 2e9+10;
struct work1{
int n,m,mxn;
struct node{int pos[N];bool flg;}a[N];
int d[N][N],p[N][N],to[M][N][N],f[M][N],g[M][N],tp;
int fac[G],dfac[G],pw[N],lg[M];
inline int ksm(int a,int b){
int c = 1;for(;b;b>>=1,a = 1ll*a*a%mo)if(b&1)c = 1ll*c*a%mo;return c;
}
inline void init_fac(int n,int m){
fac[0] = dfac[0] = 1;
FOR(i,1,n)fac[i] = 1ll*fac[i-1]*i%mo;
dfac[n] = ksm(fac[n],mo-2);
REP(i,n-1,1)dfac[i] = 1ll*dfac[i+1]*(i+1)%mo;
pw[0] = 1;
FOR(i,1,m)lg[pw[i]=pw[i-1]<<1] = i;
}
inline void pre(int &d,int &p,node &A,node &B){
d = 0;
FOR(i,1,m)d+=std::abs(A.pos[i]-B.pos[i]);
p = fac[d];
FOR(i,1,m)p = 1ll*p*dfac[std::abs(A.pos[i]-B.pos[i])]%mo;
}
inline void renew(int &f0,int &g0,int f1,int g1){
if(f0>f1)f0 = f1,g0 = g1;
else if(f0==f1)g0 = (0ll+g0+g1)%mo;
}
inline void add(int &x,int y){
if((x+=y)>=mo)x-=y;
}
struct node1{
int x,y,d;bool operator<(const node1 &A)const {return d<A.d;}
}c[N*N];
bool del[N],flg[N*N];
int tstk[N*N][N],ttp[N*N];
inline void solve(){
//rd
readx(m),readx(n);
FOR(i,1,n)FOR(j,1,m)readx(a[i].pos[j]);
FOR(i,1,n)readx(a[i].flg);
//pre
FOR(i,1,n)FOR(j,i+1,n)pre(d[i][j],p[i][j],a[i],a[j]),d[j][i] = d[i][j],p[j][i] = p[i][j];
//to
tp = 0;
FOR(i,1,n)FOR(j,i+1,n)c[++tp] = {i,j,d[i][j]},flg[tp] = 1;
std::sort(c+1,c+1+tp);
FOR(t,1,tp){
int x = c[t].x,y = c[t].y;
ttp[t] = 0;
FOR(z,1,n){
if(z!=x&&z!=y&&d[x][z]+d[z][y]==d[x][y]){
tstk[t][++ttp[t]] = z;
}
}
}
mxn = pw[n]-1;
FOR(sta,0,mxn-1){
FOR(i,0,n-1)del[i+1] = sta&pw[i];
FOR(t,1,tp){
int x = c[t].x,y = c[t].y;
if(sta&&del[x]==del[y])continue;
to[sta][y][x] = to[sta][x][y] = p[x][y];
if(sta&&flg[t])continue;
if(!del[x])std::swap(x,y);
FOR(tid,1,ttp[t]){
int z = tstk[t][tid];
if(del[z])continue;
to[sta][x][y] = (to[sta][x][y]-1ll*to[sta][x][z]*p[z][y])%mo;
flg[t] &= 0;
}
to[sta][y][x] = to[sta][x][y];
}
}
//f
FOR(S,0,mxn)FOR(i,0,n-1)f[S][i] = nf,g[S][i] = 0;
FOR(i,1,n)if(a[i].flg)f[pw[i-1]][i-1] = 0,g[pw[i-1]][i-1] = 1;
FOR(S,1,mxn){
for(int j0 = S,t0,x0,T;j0;j0&=j0-1){
t0 = j0&-j0,x0 = lg[t0];
T = S^t0;
for(int j1 = T,t1,x1;j1;j1&=j1-1){
t1 = j1&-j1,x1 = lg[t1];
if(to[T][x1+1][x0+1])renew(f[S][x0],g[S][x0],f[T][x1]+d[x1+1][x0+1],1ll*g[T][x1]*to[T][x1+1][x0+1]%mo);
}
}
}
int f0 = nf,g0 = 0;
FOR(i,0,n-1)renew(f0,g0,f[mxn][i],g[mxn][i]);
if(f0==nf)puts("NIE");
else output(f0),putchar(' '),output((0ll+g0+mo)%mo),putchar(10);
}
void main(){
init_fac(G-1,N-1);
int t;for(readx(t);t--;solve());
}
}A;
signed main(){
freopen("treasure.in","r",stdin);
freopen("treasure.out","w",stdout);
A.main();
return 0;
}
t4


一个上升段的贡献为 \(\dfrac{len(len+1)}{2}\)。
如果非常细致的分类讨论可以做到 \(O(1)\) 得到交换两个点对答案的影响;
考虑交换对数是 \(O(n^2)\) 的,应当统一枚举一个点,考虑其它点与其交换的影响。
性质:如果交换两个上升段中间的点肯定不优。
记 \(g_x\) 表示 \(x\) 位置所在连续段编号,就可以把 \(|g_x-g_y| = 1\) 的情况特判掉。
然后还可以把 \((1,x),(x,n)\) 的情况特判掉。
然后考虑 \(x\) 位置被换成了 \(a_y\) 的贡献。
可以对 \(a_y\) 的大小讨论,分成 \([1,\min(a_{x-1},a_{x+1})),(a_{x-1},a_{x+1}),(a_{x+1},a_{x-1}),(\max(a_{x-1},a_{x+1}),n]\) 这几种情况,然后就可以得到其对连续段的影响,进而得到其对贡献的影响。
不妨钦定 \(x\) 是段的端点。从小到大枚举 \(a_y\),这样每个位置 \(a_y\) 对位置 \(x\) 的变化是 \(O(1)\) 的;同时 \(a_x\) 对位置 \(y\) 的贡献也可以维护权值线段树查询;每次查询前删除 \(|g_x-g_y| \leq 1\) 的位置,删除位置的总和是 \(O(n)\) 的。
时间复杂度 \(O(n)\)。
思想:通过扫描线把值域的限制消除掉;实际上在 \(|g_x-g_y| \leq 1\) 并不关心位置的限制。
std::
#include<bits/stdc++.h>
// #pragma GCC optimize("Ofast,no-stack-protector,fast-math",3)
#define cln cerr<<"Line: "<<__LINE__<<" "
#define pct __builtin_popcountll
#define ctz __builtin_ctzll
#define mkp make_pair
#define MST(x) memset(x,0,sizeof(x))
#define all(x) x.begin(),x.end()
using namespace std;
constexpr int N=(1<<21)+100,_g=3,M1=1e9+7,M2=1e9+9,M=998244353;
namespace fast_io{
char buf[N+10],*p1,*p2,c;
#define gc (p1==p2&&(p2=(p1=buf)+fread(buf,1,N,stdin),p1==p2))?EOF:*p1++
template<typename _Tp>
void read(_Tp &x){
int f=0;for(c=gc;c<48;c=gc)f^=c=='-';
for(x=0;c>47;x=(x<<1)+(x<<3)+(48^c),c=gc);
if(f)x=-x;
}
template<typename _Tp,typename..._tps>
void read(_Tp &x,_tps&...y){read(x),read(y...);}
char ob[N+100],stk[505];int tp,ot;
void fls(){fwrite(ob,1,ot,stdout),ot=0;}
int cntt;
template<typename _Tp>
static inline void write(_Tp x,char c){
if(!cntt)atexit(fls),cntt=1;
while(x>9)stk[++tp]=48^(x%10),x/=10;
for(ob[ot++]=48^x;tp;ob[ot++]=stk[tp--]);
ob[ot++]=c;if(ot>N)fls();
}
}using fast_io::read;
using fast_io::write;
using ll=long long;
#define pli pair<ll,int>
#define pii pair<int,int>
using ul=unsigned long long;
using ld=double;
mt19937_64 rg(random_device{}());
const ll INF=3e18;
template<typename tp1,typename tp2>
void ckmx(tp1 &x,const tp2 &y){if(x<y)x=y;}
template<typename tp1,typename tp2>
void ckmn(tp1 &x,const tp2 &y){if(x>y)x=y;}
void add(int &x,int y){if((x+=y)>=M)x-=M;}
void del(int &x,int y){if((x-=y)<0)x+=M;}
void add(int &x,ul y,int z){x=(y*z+x)%M;}
void del(int &x,ul y,int z){if((x-=y*z%M)<0)x+=M;}
int qp(ll a,ll x=M-2){
int res=1;for(;x;x>>=1,a=a*a%M)
(x&1)&&(res=a*res%M);return res;
}
struct NTP{};
namespace MATH{
vector<int>jc,nv;
int dv2(int x){return x&1?x+M>>1:x>>1;}
int C(int n,int m){
assert(m<=n);
return 1ll*jc[n]*nv[m]%M*nv[n-m]%M;
}
int P(int n,int m){
return 1ll*jc[n]*nv[n-m]%M;
}
int D(int n,int m){
if(n<0||m<0)return 0;
if(!n)return 1;
if(!m)return 0;
return C(n+m-1,m-1);
}
void init(int n,int tp=1){
int x;
jc.resize(n+2),nv.resize(n+2);
jc[0]=nv[0]=jc[1]=nv[1]=1;
for(x=2;x<=n;++x){
jc[x]=1ll*x*jc[x-1]%M;
nv[x]=ll(M-M/x)*nv[M%x]%M;
}
if(tp)for(x=1;x<=n;++x)nv[x]=1ll*nv[x-1]*nv[x]%M;
}
}
struct DET{
int a[3005][3005],n;
int run(){
if(!n)return 1;
int x,y,z,k,res=1;
for(x=1;x<=n;++x){
for(y=x;y<=n&&!a[y][x];++y);
if(y>n)return 0;
if(y>x){
for(k=1;k<=n;++k)swap(a[x][k],a[y][k]);
res&&(res=M-res);
}
k=qp(a[x][x]);
res=1ll*res*a[x][x]%M;
for(z=1;z<=n;++z)
a[x][z]=1ll*a[x][z]*k%M;
for(y=1;y<=n;++y)
if(x!=y){
k=a[y][x];
for(z=1;z<=n;++z)
del(a[y][z],a[x][z],k);
}
}
for(x=1;x<=n;++x)
res=1ll*res*a[x][x]%M;
return res;
}
}det;
ll Gcd(ll x,ll y){
if(!x||!y)return x|y;
int k=min(ctz(x),ctz(y));
ll d;y>>=ctz(y);
while(x){
x>>=ctz(x),d=x-y;
if(x<y)y=x;
if(d<0)x=-d;
else x=d;
}return y<<k;
}
using ll=long long;
using ul=unsigned long long;
constexpr int bceil(int n){return 1<<(std::__lg(n-1)+1);}
template<int mod>struct NTT{
constexpr int dil(int x){return x>>31?x+mod:x;}
constexpr int mul(ul x,int y){return x*y%mod;}
constexpr int qpow(int a,int b,int r=1){for(;b;a=mul(a,a),b>>=1){r=b&1?mul(r,a):r;}return r;}
int w[N>>1],wI[N>>1];
void init(int n){
int l=bceil(n)>>1;w[0]=wI[0]=1;
for(int i=1;i<l;i<<=1){w[i]=qpow(_g,((mod-1)>>2)/i),wI[i]=qpow(_g,mod-1-((mod-1)>>2)/i);}
for(int i=1;i<l;++i){w[i]=mul(w[i&(i-1)],w[i&-i]),wI[i]=mul(wI[i&(i-1)],wI[i&-i]);}
}
void dif(int *f,int lim){
for(int l=lim>>1,r=lim;l;l>>=1,r>>=1)
for(int*j=f,*o=w;j!=f+lim;j+=r,++o)
for(int*k=j,x,y;k!=j+l;++k)
(x=*k)>=mod&&(x-=mod),y=mul(k[l],*o),*k=x+y,k[l]=x-y+mod;
}
void dit(int *f,int lim){
for(int l=1,r=2;l<lim;l<<=1,r<<=1)
for(int*j=f,*o=wI;j!=f+lim;j+=r,++o)
for(int*k=j,x,y;k!=j+l;++k)
x=*k,y=mod-k[l],(*k=x-y)<0&&(*k+=mod),k[l]=mul(x+y,*o);
for(int i=0,p=mod-(mod-1)/lim;i<lim;++i)f[i]=1ll*f[i]*p%mod;
}
void mul(int *f,int *g,int n){
dif(f,n),dif(g,n);
for(int i=0;i<n;++i)f[i]=1ll*f[i]*g[i]%M;
dit(f,n);
}
void mul(int *f,int n){
dif(f,n);int i;
for(i=0;i<n;++i)f[i]=1ll*f[i]*f[i]%M;
dit(f,n);
}
};
struct Htb{
static constexpr int M=1e7+19;
int hd[M+3],to[N],ct;ll ed[N];
static int hc(ul v){
v^=v<<13,v^=v>>7;
return (v^(v<<17))%M;
}
int operator[](ll x){
int &p=hd[hc(x)];
for(int i=p;i;i=to[i])
if(ed[i]==x)return i;
ed[++ct]=x,to[ct]=p;
return p=ct;
}
void clear(){while(ct)hd[hc(ed[ct--])]=0;}
}ht;
// NTT<M>ntt;
using namespace MATH;
using LL=__int128_t;
using UL=__uint128_t;
using vt=vector<int>;
int T,n,m,K,a[N],L[N],R[N],b[N],bt,p[N];
ll ans,sum,w[N];
void sol(int l,int r){
if(l==r)return;
if(l>r)swap(l,r);
ll v=sum-w[l]-w[r];
if(R[l]==R[r])v+=(1ll+l-L[l])*(R[r]-r+1);
int l1,r1,l2,r2;
if(l>1&&a[r]>a[l-1])l1=l-L[l-1]+1;
else l1=1;
if(r<n&&a[l]<a[r+1])r2=R[r+1]-r+1;
else r2=1;
if(l==r-1){
v+=l1+r2;
if(a[r]<a[l])v+=1ll*l1*r2;
goto lc1;
}
if(a[r]<a[l+1]&&a[l]>a[r-1]&&R[l+1]>=r-1){
r1=r2+r-l,l2=l1+r-l;
v-=1ll*l1*r2;
}else{
if(a[r]<a[l+1])r1=R[l+1]-l+1;
else r1=1;
if(a[l]>a[r-1])l2=r-L[r-1]+1;
else l2=1;
}
v+=1ll*l1*r1,v+=1ll*l2*r2;
lc1:ans=max(ans,v);
}
struct dat{int x;ll v;};
vector<dat>h[N];
ll mx[N];
#define ls x<<1
#define rs x<<1|1
ll qry(int l,int r){
ll res=-1e18;
for(l+=m-1,r+=m+1;l^r^1;l>>=1,r>>=1){
if(!(l&1))ckmx(res,mx[l^1]);
if(r&1)ckmx(res,mx[r^1]);
}return res;
}
int main(){
ios::sync_with_stdio(false),cin.tie(0);
int i,j,k,l,r,x,y,z,t;
freopen("wei.in","r",stdin);
freopen("wei.out","w",stdout);
for(cin>>T;T--;){
cin>>n,sum=0;
for(x=1;x<=n;++x)cin>>a[x],p[a[x]]=x;
for(l=1;l<=n;l=r+1){
for(r=l;r<n&&a[r+1]>a[r];++r);
for(i=l;i<=r;++i)L[i]=l,R[i]=r;
sum+=(1ll+r-l)*(r-l+2)/2;
}ans=sum;
for(x=1;x<=n;++x)w[x]=(1ll+x-L[x])*(R[x]-x+1);
for(k=2;k<=n;++k)sol(1,k);
for(k=1;k<n;++k)sol(k,n);
m=1<<__lg(n)+1;
for(x=0;x<m+m;++x)mx[x]=-1e18;
for(k=2;k<n;++k)
if(k==L[k]||k==R[k]){
l=a[k-1],r=a[k+1];
ll v=-w[k];
if(l<r){
h[1].push_back({k,v+R[k+1]-k+1});
h[l].push_back({k,(1ll+k-L[k-1])*(R[k+1]-k+1)+v});
h[r].push_back({k,v+k-L[k-1]+1});
}else{
h[1].push_back({k,v+R[k+1]-k+1});
h[r].push_back({k,v+1});
h[l].push_back({k,v+k-L[k-1]+1});
}
}
for(k=1;k<=n;++k){
for(dat at:h[k]){
mx[x=m+a[at.x]]=at.v;
for(x>>=1;x;x>>=1)
mx[x]=max(mx[ls],mx[rs]);
}h[k].clear();
bt=0,x=p[k];
if(x==1||x==n)continue;
for(l=x,r=0;l&&r<3;l=L[l]-1,++r)
b[++bt]=a[L[l]],b[++bt]=a[R[l]];
for(l=x,r=0;l<n&&r<3;l=R[l]+1,++r)
b[++bt]=a[L[l]],b[++bt]=a[R[l]];
for(i=1;i<=bt;++i)sol(p[b[i]],x);
b[++bt]=0,b[++bt]=n+1;
b[++bt]=a[x-1],b[++bt]=a[x+1];
sort(b+1,b+bt+1);
bt=unique(b+1,b+bt+1)-b-1;
for(i=2;i<=bt;++i)
if(b[i-1]<b[i]-1){
l=b[i-1]+1,r=b[i]-1;
ll v=sum+qry(l,r)-w[x];
if(r<=a[x+1]&&l>=a[x-1])v+=(1ll+x-L[x-1])*(R[x+1]-x+1);
else{
++v;
if(r<=a[x+1])v+=R[x+1]-x;
if(l>=a[x-1])v+=x-L[x-1];
}ckmx(ans,v);
}
}
printf("%lld\n",ans%(1ll<<32));
}
return 0;
}

浙公网安备 33010602011771号