# 6.26联考题解

A：

code：

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

const int maxn = 12000000;

int C,L;
char str[110];
int nowi[maxn],sum;

int sta[maxn],top;
char temp[maxn],ans[maxn]; int ansn;
void solve(int x)
{
sta[top=1]=x;
while(top)
{
if(temp[top]!=0) ans[++ansn]=temp[top],temp[top]=0;
x=sta[top];
if(nowi[x]<C)
{
int y=(x*C+nowi[x])%sum;
temp[top]=str[++nowi[x]];
sta[++top]=y;
}
else top--;
}
}

int main()
{
freopen("life.in","r",stdin);
freopen("life.out","w",stdout);

scanf("%d%d",&C,&L);
scanf("%s",str+1);
sum=1;for(int i=1;i<L;i++) sum*=C;

int x=0;
for(int i=1;i<L;i++) x=x*C;
solve(x);

printf("%d\n",L-1+ansn);
for(int i=1;i<L;i++) putchar(str[1]);
for(int i=ansn;i>=1;i--) putchar(ans[i]);
puts("");

return 0;
}


B：

$\sum _{i=l}^{r}\frac{min\left(min\left(i-l+1,r+1-i\right),rad\left[i\right]\right)}{2}$

code：

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

const int maxn = 310000;
const int maxp = maxn*30;

struct segment
{
int cnt;
int lc[maxp],rc[maxp],siz[maxp];
ll seg[maxp],seg2[maxp];
int loc,c1,c2;
void upd(int &x,const int l,const int r)
{
x=++cnt;
seg[x]=c1,seg2[x]=c2,siz[x]=1;
if(l==r) return;
int mid=(l+r)>>1;
loc<=mid?upd(lc[x],l,mid):upd(rc[x],mid+1,r);
}
void merge(int &x,const int &y)
{
if(!y) return;
if(!x){ x=y;return; }
siz[x]+=siz[y];
seg[x]+=seg[y],seg2[x]+=seg2[y];
merge(lc[x],lc[y]); merge(rc[x],rc[y]);
}
int lx,rx;
ll querysum1(int x,int y,const int l,const int r)
{
if(rx<l||r<lx||siz[x]==siz[y]) return 0;
if(lx<=l&&r<=rx) return seg[x]-seg[y];
int mid=(l+r)>>1;
return querysum1(lc[x],lc[y],l,mid)+querysum1(rc[x],rc[y],mid+1,r);
}
ll querysum2(int x,int y,const int l,const int r)
{
if(rx<l||r<lx||siz[x]==siz[y]) return 0;
if(lx<=l&&r<=rx) return seg2[x]-seg2[y];
int mid=(l+r)>>1;
return querysum2(lc[x],lc[y],l,mid)+querysum2(rc[x],rc[y],mid+1,r);
}
int querysiz(int x,int y,const int l,const int r)
{
if(rx<l||r<lx||siz[x]==siz[y]) return 0;
if(lx<=l&&r<=rx) return siz[x]-siz[y];
int mid=(l+r)>>1;
return querysiz(lc[x],lc[y],l,mid)+querysiz(rc[x],rc[y],mid+1,r);
}
}seg,seg2;
int root[maxn],root2[maxn];

int n,m,len;
char str[maxn];

int main()
{
freopen("gene.in","r",stdin);
freopen("gene.out","w",stdout);

scanf("%d%d",&n,&m);
scanf("%s",str+1); len=n;
S[n=0]=-1;
for(int i=1;i<=len;i++)
{
S[++n]=0;
S[++n]=str[i]-'A'+1;
}
S[++n]=0;
S[++n]=-2;

int mx=0,id=0;
for(int i=1;i<n;i++)
{

}

for(int i=1;i<n;i++)
{
seg.merge(root[i],root[i-1]);

seg2.merge(root2[i],root2[i-1]);
}

while(m--)
{
int l,r; scanf("%d%d",&l,&r);
l=2*l-1,r=2*r+1; int mid=(l+r)>>1;
ll ans=0;

seg.lx=l,seg.rx=n,ans+=seg.querysum1(root[mid],root[l-1],0,n);

seg.lx=0,seg.rx=l-1;
ll si=seg.querysum2(root[mid],root[l-1],0,n);
int siz=seg.querysiz(root[mid],root[l-1],0,n);
ans+=si-(ll)siz*((l-1)/2);

seg2.lx=0,seg2.rx=r,ans+=seg2.querysum1(root2[r],root2[mid],0,n);

seg2.lx=r+1,seg2.rx=n;
si=seg2.querysum2(root2[r],root2[mid],0,n);
siz=seg2.querysiz(root2[r],root2[mid],0,n);
ans+=(ll)siz*((r+1)/2)-si;

printf("%lld\n",ans);
}

return 0;
}


C：

$f\left[i\right]\left[j\right]$$f[i][j]$表示对于1~j，建了$i$$i$个关键点，最后一个关键点在$j$$j$最小花费

code：

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define fir first
#define sec second
#define mp make_pair
#define pb push_back
#define SZ(x) (int)x.size()
#define lc (x<<1)
#define rc (x<<1|1)
using namespace std;

const int maxn = 41000;

int n,m,U;
int dis[maxn];
int C[maxn],R[maxn],P[maxn];
vector< pair<int,int> >V[maxn];
ll rsum[maxn];

struct segment
{
ll seg[maxn<<2],fl[maxn<<2];
int segp[maxn<<2];
void init(int x,const int l,const int r)
{
seg[x]=fl[x]=0; segp[x]=l;
if(l==r) return;
int mid=(l+r)>>1;
init(lc,l,mid); init(rc,mid+1,r);
}
void pushdown(int x)
{
if(!fl[x])return;
ll c=fl[x];fl[x]=0;
seg[lc]+=c,seg[rc]+=c;
fl[lc]+=c,fl[rc]+=c;
}
void pushup(int x)
{
int y=seg[lc]<=seg[rc]?lc:rc;
seg[x]=seg[y],segp[x]=segp[y];
}
int lx,rx,c;
void upd(int x,const int l,const int r)
{
if(rx<l||r<lx) return;
if(lx<=l&&r<=rx) { seg[x]+=c,fl[x]+=c;return; }
pushdown(x);
int mid=(l+r)>>1;
upd(lc,l,mid); upd(rc,mid+1,r);
pushup(x);
}
ll nowmin;
int nowre;
void query(int x,const int l,const int r)
{
if(rx<l||r<lx) return;
if(lx<=l&&r<=rx)
{
if(nowmin==-1||seg[x]<nowmin) nowmin=seg[x],nowre=segp[x];
return;
}
pushdown(x);
int mid=(l+r)>>1;
query(lc,l,mid); query(rc,mid+1,r);
}
}seg;

struct data
{
ll f;
int k;
}f[maxn],ans;
int dp(int mid)
{
seg.init(1,0,n);

f[0]=(data){0,0};
for(int i=1;i<=n;i++)
{
seg.nowmin=-1;
seg.lx=0,seg.rx=i-1,seg.query(1,0,n);

f[i]=(data){seg.nowmin+mid+C[i],f[seg.nowre].k+1};
seg.lx=seg.rx=i,seg.c=f[i].f,seg.upd(1,0,n);

for(int j=0;j<SZ(V[i]);j++)
{
seg.lx=0,seg.rx=V[i][j].fir-1,seg.c=V[i][j].sec;
seg.upd(1,0,n);
}
}
ans.f=-1;
for(int i=1;i<=n;i++)
{
f[i].f+=rsum[i+1];
if(ans.f==-1||ans.f>f[i].f) ans=f[i];
}
return ans.k;
}

ll Solve()
{
int l=0,r=U;
ll re;
while(l<=r)
{
int mid=((ll)l+r)>>1;
if(dp(mid)<=m) r=mid-1,re=ans.f-(ll)mid*m;
else l=mid+1;
}
return re;
}

int main()
{
freopen("jhaha.in","r",stdin);
freopen("jhaha.out","w",stdout);

scanf("%d%d",&n,&m);
for(int i=2;i<=n;i++) scanf("%d",&dis[i]);
for(int i=1;i<=n;i++) scanf("%d",&C[i]);
for(int i=1;i<=n;i++) scanf("%d",&R[i]);
for(int i=1;i<=n;i++) scanf("%d",&P[i]),U+=P[i];

for(int i=1;i<=n;i++)
{
int l=1,r=i;
while(l<=r)
{
int mid=(l+r)>>1;
if(dis[i]-dis[mid]<=R[i]) r=mid-1;
else l=mid+1;
}
int L=r+1; rsum[L]+=P[i];

l=i,r=n;
while(l<=r)
{
int mid=(l+r)>>1;
if(dis[mid]-dis[i]<=R[i]) l=mid+1;
else r=mid-1;
}
V[l-1].pb(mp(L,P[i]));
}
for(int i=n-1;i>=1;i--) rsum[i]+=rsum[i+1];

printf("%lld\n",Solve());

return 0;
}