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;
}
posted @ 2025-11-20 07:54  rabbit_mygo  阅读(16)  评论(0)    收藏  举报