对树分层 d p dp dp即可
f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]从大到小第 i i i个, j j j个当前层的点, k k k个下一层的点
要么选一个当前层,要么当前层全部拆到下和下下层
#include
using namespace std;
#define cs const
#define pb push_back
#define pii pair
#define fi first
#define se second
#define ll long long
#define bg begin
namespace IO{
cs int rlen=1<<22|1;
char ibuf[rlen],*ib,*ob;
inline char gc(){
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,rlen,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=0;
while(!isdigit(ch))f=ch=='-',ch=gc();
while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
return f?-res:res;
}
}
using IO::read;
template<typename tp>inline void chemx(tp &a,tp b){(a<b)?(a=b):0;}
template<typename tp>inline void chemn(tp &a,tp b){(a>b)?(a=b):0;}
cs int N=755;
int a[N],s[N],n;
ll f[N][N],inf;
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
n=read();
for(int i=1;i<=n;i++)a[i]=read();
sort(a+1,a+n+1,greater<int>());
for(int i=n;i;i--)s[i]=s[i+1]+a[i];
memset(f,127/3,sizeof(f));inf=f[0][0];
f[1][1]=s[1];
for(int i=1;i<=n;i++){
int vl=s[i];
for(int j=0,l=n-i+1;j<=l;j++)
for(int k=0,l2=n-i+1-j;k<=l2;k++){
chemn(f[j+k][j],f[j][k]+vl);
}
for(int j=1,l=n-i+1;j<=l;j++)
for(int k=0,l2=n-i+1-j;k<=l2;k++)
f[j-1][k]=f[j][k];
}
cout<<f[0][0];return 0;
}
神必东西
实际上记左右第一个断点和上一个似乎可以 d p dp dp?
但感觉不可能有人写的出来
考虑两个11之间一定不可达,然后全赋成1
然后这样状态莫名就很少了
#include
using namespace std;
#define cs const
#define pb push_back
#define pii pair
#define fi first
#define se second
#define ll long long
#define bg begin
namespace IO{
cs int rlen=1<<22|1;
char ibuf[rlen],*ib,*ob;
inline char gc(){
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,rlen,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=0;
while(!isdigit(ch))f=ch=='-',ch=gc();
while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
return f?-res:res;
}
inline void readstring(char *s){
int top=0;char ch=gc();
while(isspace(ch))ch=gc();
while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
s[top+1]='\0';return;
}
}
using IO::read;
using IO::readstring;
template<typename tp>inline void chemx(tp &a,tp b){(a<b)?(a=b):0;}
template<typename tp>inline void chemn(tp &a,tp b){(a>b)?(a=b):0;}
int mod;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a<b?a-b+mod:a-b;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int &a,int b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int &a,int b){a=a<b?a-b+mod:a-b;}
inline void Mul(int &a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))if(b&1)Mul(res,a);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
typedef unsigned long long ul;
int n,iv4;
struct bt{
ul a,b;
bt():a(0),b(0){}
bt(ul _a,ul _b):a(_a),b(_b){}
void set(int i){(i<64?a:b)|=1ull<<(i&63);}
bool get(int i)cs{return ((i<64?a:b)>>(i&63))&1;}
bt operator >>(int i)cs{
if(i<64)return bt(((b&((1ull<<i)-1))<<(64-i))|(a>>i),b>>i);
return bt(b>>(i-64),0);
}
bt operator <<(int i)cs{
if(i<64)return bt(a<<i,(b<<i)|(a>>(64-i)));
return bt(0,a<<(i-64));
}
bt operator |(cs bt &x)cs{return bt(a|x.a,b|x.b);}
bt operator &(cs bt &x)cs{return bt(a&x.a,b&x.b);}
bt operator &(int x)cs{return bt(a&x,0);}
bt resize()cs{
if(n<64)return bt(a&((1ull<<n)-1),0);
if(n==64)return *this;
return bt(a,b&((1ull<<(n-64))-1));
}
bt rever()cs{
bt x;if(get(0))x.set(0);
for(int i=1;i<n;i++)if(get(i))x.set(n-i);
return x;
}
bool operator <(cs bt &x)cs{
return (b==x.b)?(a<x.a):b<x.b;
}
void cover(){
int l=n+1,r=-1;
for(int i=1;i+1<n;i++)
if(get(i)&&get(i+1))l=min(i,l),r=max(i,r);
if(l+2>=r)return;
for(int i=l;i<=r+1;i++)set(i);
}
};
map<bt,int>f;
bt move(bt x,int k){
switch(k){
case 1:return (x>>1)|((x&1)<<(n-1));
case 2:return (x>>2)|((x&3)<<(n-2));
case -1:return ((x<<1)|(x>>(n-1))).resize();
case -2:return ((x<<2)|(x>>(n-2))).resize();
}
}
int dfs(bt x){
if(x.get(0))return 0;
x.set(0),x.cover();
x=min(x,x.rever());
if(f.count(x))return f[x];
int res=0;
Add(res,dfs(move(x,1)));
Add(res,dfs(move(x,2)));
Add(res,dfs(move(x,-1)));
Add(res,dfs(move(x,-2)));
Mul(res,iv4);
return f[x]=res+1;
}
int main(){
cin>>n>>mod;iv4=Inv(4);
if(n==1)return cout<<1,0;
cout<<dfs(bt());
}
在回文树上树剖维护即可
注意先求出每个位置的最长回文前后缀所在的点
这需要离线建出 p a m pam pam后前后后前分别跑一次
还有特殊处理一下 l c a lca lca是不是最长后缀
由于考试时脑残写的双向 p a m pam pam懒得改了
#include
using namespace std;
#define cs const
#define pb push_back
#define pii pair
#define fi first
#define se second
#define ll long long
#define bg begin
namespace IO{
cs int rlen=1<<22|1;
char ibuf[rlen],*ib,*ob;
inline char gc(){
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,rlen,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=0;
while(!isdigit(ch))f=ch=='-',ch=gc();
while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
return f?-res:res;
}
inline void readstring(char *s){
int top=0;char ch=gc();
while(isspace(ch))ch=gc();
while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
s[top+1]='\0';return;
}
}
using IO::read;
using IO::readstring;
template<typename tp>inline void chemx(tp &a,tp b){(a<b)?(a=b):0;}
template<typename tp>inline void chemn(tp &a,tp b){(a>b)?(a=b):0;}
cs int N=3e5+5;
int L,R,cnt,n,q,tot;
int s[N];
int pl[N],pr[N],pos[N];
struct opt{
int a,b,c,d;
}qy[N];
int pt[N],kd[N];
pii qt[N];
vector<int> e[N],pre;
int fa[N],len[N],in[N],dfn,id[N],dep[N],siz[N],son[N],top[N];
namespace seg{
#define lc (u<<1)
#define rc ((u<<1)|1)
#define mid ((l+r)>>1)
cs int N=::N<<2;
ll coef[N],tag[N],sm[N];
void pushnow(int u,ll k){
tag[u]+=k,sm[u]+=coef[u]*k;
}
void pushdown(int u){
if(!tag[u])return;
pushnow(lc,tag[u]);
pushnow(rc,tag[u]);
tag[u]=0;
}
void build(int u,int l,int r){
if(l==r){coef[u]=len[id[l]];return;}
build(lc,l,mid),build(rc,mid+1,r);
coef[u]=coef[lc]+coef[rc];
}
void update(int u,int l,int r,int st,int des,int k){
if(st<=l&&r<=des)return pushnow(u,k);
pushdown(u);
if(st<=mid)update(lc,l,mid,st,des,k);
if(mid<des)update(rc,mid+1,r,st,des,k);
sm[u]=sm[lc]+sm[rc];
}
ll query(int u,int l,int r,int st,int des){
if(st<=l&&r<=des)return sm[u];
pushdown(u);ll res=0;
if(st<=mid)res+=query(lc,l,mid,st,des);
if(mid<des)res+=query(rc,mid+1,r,st,des);
return res;
}
#undef lc
#undef rc
#undef mid
}
void dfs(int u){
siz[u]=1;
for(int i=0;i<e[u].size();i++){
int v=e[u][i];
if(v==fa[u])continue;
dep[v]=dep[u]+1,dfs(v),siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u,int tp){
in[u]=++dfn,id[dfn]=u,top[u]=tp;
if(son[u])dfs2(son[u],tp);
for(int i=0;i<e[u].size();i++){
int v=e[u][i];
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
inline int find(int u,int k){
while(len[top[u]]>k)u=fa[top[u]];
int l=in[top[u]],r=in[u],res=l;
while(l<=r){
int mid=(l+r)>>1;
if(len[id[mid]]<=k)l=mid+1,res=mid;
else r=mid-1;
}return id[res];
}
namespace pam{
int nxt[N][26],lastl,lastr,fa[N],len[N];
inline void init(){
memset(s,-1,sizeof(s));
len[1]=-1,fa[0]=1;tot=1;
}
inline int find(int p,int d){
if(d==0){
while(s[R]!=s[R-len[p]-1])p=fa[p];return p;
}
while(s[L]!=s[L+len[p]+1])p=fa[p];return p;
}
inline void getpos(){
int p=0;int nl=L,nr=R;
for(R=nl;R<=nr;R++){
p=nxt[find(p,0)][s[R]];
pl[R]=p;
}
p=0;
for(L=nr;L>=nl;L--){
p=nxt[find(p,1)][s[L]];
pr[L]=p;
}L=nl,R=nr;
}
void insert(int c,int d,int ps){
int p=find(d?lastl:lastr,d);
if(!nxt[p][c]){
int u=++tot;
len[u]=len[p]+2;
fa[u]=nxt[find(fa[p],d)][c];
nxt[p][c]=u;
}
if(d==0){
lastr=nxt[p][c];
if(len[lastr]==R-L+1)lastl=lastr;
if(ps)pos[ps]=lastr+1;
else pre.pb(lastr+1);
}
else{
lastl=nxt[p][c];
if(len[lastl]==R-L+1)lastr=lastl;
if(ps)pos[ps]=lastl+1;
else pre.pb(lastl+1);
}
}
}
char op[10];
inline int Lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
u=fa[top[u]];
}return dep[u]<dep[v]?u:v;
}
void update(int u,int k){
while(u){
seg::update(1,1,tot,in[top[u]],in[u],k);
u=fa[top[u]];
}
}
ll query(int u,int v,int kd){
ll res=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
res+=seg::query(1,1,tot,in[top[u]],in[u]);
u=fa[top[u]];
}
if(dep[u]<dep[v])swap(u,v);
if(in[v]+kd<=in[u])res+=seg::query(1,1,tot,in[v]+kd,in[u]);
return res;
}
int main(){
pam::init();L=1e5+1,R=1e5;
n=read(),q=read();
for(int i=1;i<=n;i++)s[++R]=read(),pam::insert(s[R],0,0);
for(int i=1;i<=q;i++){
readstring(op);
if(op[1]=='a'){
int c=read();
if(op[4]=='l'){pt[i]=1;
s[--L]=c,pam::insert(c,1,i);
}
else{pt[i]=2;
s[++R]=c,pam::insert(c,0,i);
}
}
else{
int l1=L+read()-1,r1=L+read()-1,l2=L+read()-1,r2=L+read()-1;
qy[i]=(opt){l1,r1,l2,r2};
if(op[6]=='l')pt[i]=3;
else pt[i]=4;
}
}
pam::getpos();
// for(int i=L;i<=R;i++)cout<
for(int i=0;i<=tot;i++)len[i+1]=pam::len[i],fa[i+1]=pam::fa[i]+1;
tot++;fa[2]=0;len[2]=0;
for(int i=1;i<=tot;i++)if(i!=2)e[fa[i]].pb(i);
dfs(2),dfs2(2,2);
for(int i=1;i<=q;i++)if(pt[i]==3||pt[i]==4){
int l1=qy[i].a,r1=qy[i].b,l2=qy[i].c,r2=qy[i].d,p1,p2;
if(pt[i]==3)p1=find(pl[r1]+1,r1-l1+1),p2=find(pl[r2]+1,r2-l2+1);
else p1=find(pr[l1]+1,r1-l1+1),p2=find(pr[l2]+1,r2-l2+1);
int l=len[Lca(p1,p2)];qt[i]=pii(p1,p2);
if(pt[i]==3)kd[i]=(l1+l<=r1&&l2+l<=r2&&s[r1-l]==s[r2-l]);
else kd[i]=(l1+l<=r1&&l2+l<=r2&&s[l1+l]==s[l2+l]);
}
seg::build(1,1,tot);
for(int i=0;i<pre.size();i++)update(pre[i],1);
for(int i=1;i<=q;i++){
if(pt[i]<=2){
update(pos[i],1);
}
else{
cout<<query(qt[i].fi,qt[i].se,kd[i])<<'\n';
}
}return 0;
}