A. 黑桃城
得分:100分
解析:
这题挺水的吧,直接把dfs之后的序列映射到线段树的一段区间维护即可
反正我40分钟就A了,自认为还是挺简单的。
这题好像也是比赛中AC人数最多的,。。。
还有就是注意不要用不同步的cin,小心TLE
然后 我好像找到了原题 CF077E Danil and a Part-time Job
除输入外一模一样。。。
#include
#include
#include
#include
#include
#include
#include
#include
#define For(i,j,k) for(ll i=j;i<=k;++i)
#define Dow(i,j,k) for(ll i=k;i>=j;--i)
#define M 100010
#define pb push_back
#define ll long long
using namespace std;
inline ll read()
{
ll t=0,f=1;char c=getchar();
while(c<'0'||c>'9') {c=getchar();}
while(c<='9'&&c>='0') t=t*10+c-48,c=getchar();
return t*f;
}
int poi[M<<2],nxt[M<<2],f[M<<2],cnt,n,m;
char opt[10],s[M<<2];
struct tree{int v,sz;} tr[M<<2];
int tag[M<<2];
int in[M<<2],out[M<<2],tim,on[M<<2],to[M<<2];
inline void add(int x,int y){
poi[++cnt]=y;
nxt[cnt]=f[x];
f[x]=cnt;
}
inline void dfs(int x,int fa){
in[x]=++tim;to[tim]=x;
for(int i=f[x];i;i=nxt[i]){
if(poi[i]==fa) continue;
dfs(poi[i],x);
}
out[x]=tim;
}
inline void up(int x){
tr[x].v=tr[x<<1|1].v+tr[x<<1].v;
tr[x].sz=tr[x<<1|1].sz+tr[x<<1].sz;
}
inline void build(int x,int l,int r){
if(l==r){
tr[x].v=on[to[l]];
tr[x].sz=1;
return;
}
int mid=l+r>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
up(x);
}
inline void push(int x){
if(tag[x]){
tag[x<<1]^=1;tag[x<<1|1]^=1;
tr[x<<1].v=tr[x<<1].sz-tr[x<<1].v;tr[x<<1|1].v=tr[x<<1|1].sz-tr[x<<1|1].v;
tag[x]=0;
}
}
inline int ask(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr) return tr[x].v;
int mid=l+r>>1;
push(x);
int sum=0;
if(ql<=mid) sum+=ask(x<<1,l,mid,ql,qr);
if(qr >mid) sum+=ask(x<<1|1,mid+1,r,ql,qr);
up(x);
return sum;
}
inline void change(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr){
tr[x].v=tr[x].sz-tr[x].v;
tag[x]^=1;
return;
}
int mid=l+r>>1;
push(x);
if(ql<=mid) change(x<<1,l,mid,ql,qr);
if(qr >mid) change(x<<1|1,mid+1,r,ql,qr);
up(x);
}
int main(){
n=read(),m=read();
scanf("%s",&s) ;
For (i,1,n) on[i]=s[i-1]-'0' ;
For (i,1,n-1){
int a=read(),b=read() ;
add(a,b) ;
}
dfs(1,1);
build(1,1,n);
For(i,1,m){
scanf("%s",opt+1);
if(opt[1]=='Q') {
int x=read();
printf("%d\n",ask(1,1,n,in[x],out[x]));
}
else{
int x=read();
change(1,1,n,in[x],out[x]);
}
}
}
B. 红五月
得分:42分
预期:42 ~ 67 分
这题其实是我花费时间最长的一道题目,几乎占用了我一半的时间,以至于我没有拿到C题的49分,没有上两百(第一)
我先打了暴力,前42分其实很好拿,直接暴力修改判断即可,但这么简单我却打了1个多快2个小时,这得要加强一下码力啊。
这题其实就是一个动态查询,修改的树上问题,其实一个树剖就能搞定。
关键思考修改操作
考虑跨区间的情况,细心讨论一下。
巨佬现场67代码(%%%PQF):
#include
using namespace std;
int fa[100001],d[100001];
vector <int> E[100001];
int c[200001];
int n,m,a[100001],u,v,s0,s1,num;
int dfn[100001],seq[100001];
int lca (int u,int v)
{
if (d[u]!=d[v])
{
if (d[u]while (d[u]>d[v])
u=fa[u];
}
while (u!=v)
u=fa[u],v=fa[v];
return u;
}
string str;
void dfs (int x)
{
for (auto i:E[x])
{
if (i==fa[x]) continue;
fa[i]=x;
d[i]=d[x]+1;
dfs(i);
}
return;
}
void dfs1 (int x)
{
dfn[++num]=x;
seq[x]=num;
for (auto i:E[x])
{
if (i==fa[x]) continue;
fa[i]=x;
d[i]=d[x]+1;
dfs1(i);
}
return;
}
struct data
{
int l,r,len,lazy,s;
}tr[400001];
void build (int x,int l,int r)
{
tr[x].l=l;
tr[x].r=r;
tr[x].len=r-l+1;
tr[x].lazy=-1;
if (l==r)
{
tr[x].s=a[seq[l]];
return;
}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
tr[x].s=tr[x<<1].s+tr[x<<1|1].s;
return;
}
void pushdown (int x)
{
int p=tr[x].lazy;
tr[x<<1].lazy=p;
tr[x<<1|1].lazy=p;
tr[x<<1].s=tr[x<<1].len*p;
tr[x<<1|1].s=tr[x<<1|1].len*p;
tr[x].lazy=-1;
}
int sum (int x,int l,int r)
{
int ll=tr[x].l,rr=tr[x].r;
if (l<=ll && r>=rr) return tr[x].s;
if (ll>r) return 0;
if (rrreturn 0;
if (tr[x].lazy!=-1) pushdown(x);
int mid=(ll+rr)>>1;
if (l>mid) return sum(x<<1|1,l,r);
else if (r<=mid) return sum(x<<1,l,r);
else return sum(x<<1,l,mid)+sum(x<<1|1,mid+1,r);
}
void change (int x,int l,int r,int s)
{
if (l>r) return;
//printf("%d %d %d %d\n",x,l,r,s);
int ll=tr[x].l,rr=tr[x].r;
if (l<=ll && r>=rr)
{
tr[x].lazy=s;
tr[x].s=tr[x].len*s;
return;
}
if (ll>r) return;
if (rrreturn;
if (tr[x].lazy!=-1) pushdown(x);
int mid=(ll+rr)>>1;
if (l>mid) change(x<<1|1,l,r,s);
else if (r<=mid) change(x<<1,l,r,s);
else { change(x<<1,l,mid,s); change(x<<1|1,mid+1,r,s); }
tr[x].s=tr[x<<1].s+tr[x<<1|1].s;
return;
}
bool doit (int u,int v)
{
int fu=dfn[u],fv=dfn[v];
if (fu>fv)
{
swap(fu,fv);
swap(u,v);
}
int z1=sum(1,fu,fv);
int z0=fv-fu+1-z1;
//printf("%d %d\n",z0,z1);
if ((z0&1) && (z1&1)) return false;
if (z0&1)
{
change(1,fu,fu+z0/2-1,0);
change(1,fu+z0/2,fu+z0/2+z1/2-1,1);
change(1,fu+z0/2+z1/2,fu+z0/2+z1/2,0);
change(1,fu+z0/2+z1/2+1,fu+z0/2+z1,1);
change(1,fu+z0/2+z1+1,fv,0);
return true;
}
change(1,fu,fu+z0/2-1,0);
change(1,fu+z0/2,fu+z0/2+z1-1,1);
change(1,fu+z0/2+z1,fv,0);
return true;
}
int main()
{
scanf("%d%d",&n,&m);
cin>>str;
for (int i=1;i<=n;i++)
a[i]=str[i-1]-48;
for (int i=1;i<=n-1;i++)
{
scanf("%d%d",&u,&v);
E[u].push_back(v);
E[v].push_back(u);
}
if (n<=1000)
{
dfs(1);
/*
for (int i=1;i<=n;i++)
printf("%d %d\n",fa[i],d[i]);
*/
for (int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
int w=lca(u,v);
s0=s1=0;
for (int x=u;x!=w;x=fa[x])
{
if (a[x]) s1++;
else s0++;
}
for (int x=v;x!=w;x=fa[x])
{
if (a[x]) s1++;
else s0++;
}
if (a[w]) s1++;
else s0++;
//printf("%d\n%d %d\n",w,s0,s1);
if ((s1&1) && (s0&1))
{
printf("No\n");
continue;
}
printf("Yes\n");
if (s1&1)
{
num=0;
for (int x=u;x!=w;x=fa[x])
c[++num]=x;
c[++num]=w;
num=d[u]+d[v]-2*d[w]+1;
for (int x=v;x!=w;x=fa[x])
c[num--]=x;
for (int i=1;i<=s0/2;i++)
a[c[i]]=0;
for (int i=s0/2+1;i<=s0/2+s1;i++)
a[c[i]]=1;
for (int i=s0/2+s1+1;i<=s0+s1;i++)
a[c[i]]=0;
}
else if (s0&1)
{
num=0;
for (int x=u;x!=w;x=fa[x])
c[++num]=x;
c[++num]=w;
num=d[u]+d[v]-2*d[w]+1;
for (int x=v;x!=w;x=fa[x])
c[num--]=x;
for (int i=1;i<=s0/2;i++)
a[c[i]]=0;
for (int i=s0/2+1;i<=s0/2+s1/2;i++)
a[c[i]]=1;
a[c[s0/2+s1/2+1]]=0;
for (int i=s0/2+s1/2+2;i<=s0/2+s1+1;i++)
a[c[i]]=1;
for (int i=s0/2+s1+2;i<=s0+s1;i++)
a[c[i]]=0;
}
else
{
num=0;
for (int x=u;x!=w;x=fa[x])
c[++num]=x;
c[++num]=w;
num=d[u]+d[v]-2*d[w]+1;
for (int x=v;x!=w;x=fa[x])
c[num--]=x;
for (int i=1;i<=s0/2;i++)
a[c[i]]=0;
for (int i=s0/2+1;i<=s0/2+s1;i++)
a[c[i]]=1;
for (int i=s0/2+s1+1;i<=s0+s1;i++)
a[c[i]]=0;
}
/*
for (int i=1;i<=n;i++)
printf("%d ",a[i]);
printf("\n");
num=d[u]+d[v]-2*d[w]+1;
for (int i=1;i<=num;i++)
printf("%d ",c[i]);
printf("\n");
printf("\n");
*/
}
return 0;
}
int k;
for (k=1;k<=n;k++)
if (E[k].size()==1) break;
//printf("%d\n",k);
dfs1(k);
build(1,1,n);
/*
for (int i=1;i<=n;i++)
printf("%d ",dfn[i]);
printf("\n");
for (int i=1;i<=9;i++)
printf("%d %d %d %d\n",tr[i].l,tr[i].r,tr[i].lazy,tr[i].s);
printf("\n");
*/
for (int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
if (doit(u,v)) printf("Yes\n");
else printf("No\n");
/*
for (int i=1;i<=9;i++)
printf("%d %d %d %d\n",tr[i].l,tr[i].r,tr[i].lazy,tr[i].s);
printf("\n");
*/
}
return 0;
}
/*
5 10
01011
1 5
2 4
1 3
3 2
*/
标算(%%% mjy0724 (RP- -))(太懒不想写,反正考试也写不出来):
#include
#include
#include
#include
#include
typedef long long ll ;
#define rep(i, a, b) for (int i = a; i <= b; ++ i)
const int N = 2e5 + 5 ;
using namespace std ;
char s[N] ;
int n, m, e, ter[N << 1], nxt[N << 1], lnk[N], dep[N], cnt ;
int L[N], R[N], bel[N], sz[N], pos[N], fa[N] ;
struct node {
int cov[2], len, tag ;
node() {}
node(int _x, int _y) {
cov[0] = _x ;
cov[1] = _y ;
}
node friend operator + (node a, node b) {
return node(a.cov[0] + b.cov[0], a.cov[1] + b.cov[1]) ;
}
} tr[N << 2] ;
struct intv {
int l, r ;
intv() {}
intv(int _l, int _r) {
l = _l ;
r = _r ;
}
} d[N] ;
void add(int x, int y) {
ter[++ e] = y ;
nxt[e] = lnk[x] ;
lnk[x] = e ;
}
void dfs(int p, int las) {
sz[p] = 1 ;
for (int i = lnk[p] ; i; i = nxt[i]) if (ter[i] != las) {
fa[ter[i]] = p ;
dep[ter[i]] = dep[p] + 1 ;
dfs(ter[i], p) ;
sz[p] += sz[ter[i]] ;
}
}
void Dfs(int p, int chain) {
bel[p] = chain ;
L[p] = ++ cnt ;
pos[cnt] = p ;
int k = 0 ;
for (int i = lnk[p] ; i; i = nxt[i]) {
int v = ter[i] ;
if (dep[v] > dep[p] && sz[v] > sz[k]) {
k = v ;
}
}
if (k) Dfs(k, chain) ;
for (int i = lnk[p] ; i; i = nxt[i]) {
int v = ter[i] ;
if (dep[v] > dep[p] && v != k) Dfs(v, v) ;
}
R[p] = cnt ;
}
int lca(int x, int y) {
for ( ; bel[x] != bel[y] ; ) {
if (dep[bel[x]] >= dep[bel[y]]) {
x = fa[bel[x]] ;
} else {
y = fa[bel[y]] ;
}
}
return dep[x] < dep[y] ? x : y ;
}
void psd(int p) {
int l = p << 1, r = l | 1 ;
if (tr[p].tag != - 1) {
rep(i, 0, 1) {
tr[l].cov[i] = 0 ;
tr[r].cov[i] = 0 ;
}
tr[l].tag = tr[r].tag = tr[p].tag ;
tr[l].cov[tr[p].tag] = tr[l].len ;
tr[r].cov[tr[p].tag] = tr[r].len ;
tr[p].tag = - 1 ;
}
}
void upd(int p) {
int l = p << 1, r = l | 1 ;
rep(i, 0, 1) {
tr[p].cov[i] = tr[l].cov[i] + tr[r].cov[i] ;
}
}
void build(int p, int l, int r) {
tr[p].tag = - 1 ;
tr[p].len = r - l + 1 ;
if (l == r) {
rep(i, 0, 1) {
tr[p].cov[i] = 0 ;
}
tr[p].cov[s[pos[l]] - '0'] ++ ;
return ;
}
int mid = (l + r) / 2 ;
build(p << 1, l, mid) ;
build(p << 1 | 1, mid + 1, r) ;
upd(p) ;
}
void modify(int p, int l, int r, int lx, int rx, int ave) {
if (l == lx && r == rx) {
tr[p].tag = ave ;
rep(i, 0, 1) {
tr[p].cov[i] = 0 ;
}
tr[p].cov[ave] = tr[p].len ;
return ;
}
int mid = (l + r) / 2 ;
psd(p) ;
if (rx <= mid) modify(p << 1, l, mid, lx, rx, ave) ; else
if (lx > mid) modify(p << 1 | 1, mid + 1, r, lx, rx, ave) ; else {
modify(p << 1, l, mid, lx, mid, ave) ;
modify(p << 1 | 1, mid + 1, r, mid + 1, rx, ave) ;
}
upd(p) ;
}
node query(int p, int l, int r, int lx, int rx) {
if (l == lx && r == rx) {
return tr[p] ;
}
int mid = (l + r) / 2 ;
psd(p) ;
if (rx <= mid) return query(p << 1, l, mid, lx, rx) ;
if (lx > mid) return query(p << 1 | 1, mid + 1, r, lx, rx) ;
return query(p << 1, l, mid, lx, mid) + query(p << 1 | 1, mid + 1, r, mid + 1, rx) ;
}
inline void Modi(int x, int l, int r, int c) {
if (d[x].l <= d[x].r) {
modify(1, 1, n, d[x].l + l - 1, d[x].l + r - 1, c) ;
} else {
modify(1, 1, n, d[x].l - r + 1, d[x].l - l + 1, c) ;
}
}
inline intv Solve(intv cur, int sum, int c) {
for ( ; sum > 0 ; ) {
int len = abs(d[cur.l].r - d[cur.l].l) + 1 ;
if (len - cur.r + 1 >= sum) {
Modi(cur.l, cur.r, cur.r + sum - 1, c) ;
cur.r += sum ;
if (cur.r > len) {
++ cur.l ;
cur.r = 1 ;
}
return cur ;
} else {
Modi(cur.l, cur.r, len, c) ;
sum -= len - cur.r + 1 ;
++ cur.l ;
cur.r = 1 ;
}
}
return cur ;
}
int main() {
scanf("%d%d", &n, &m) ;
scanf("%s", s + 1) ;
int x, y ;
rep(i, 1, n - 1) {
scanf("%d%d", &x, &y) ;
add(x, y) ;
add(y, x) ;
}
dfs(1, 0) ;
Dfs(1, 1) ;
build(1, 1, n) ;
for ( ; m -- ; ) {
scanf("%d%d", &x, &y) ;
int t = lca(x, y), tot = 0 ;
node res = node(0, 0) ;
for ( ; bel[x] != bel[t] ; x = fa[bel[x]]) {
res = res + query(1, 1, n, L[bel[x]], L[x]) ;
d[++ tot] = intv(L[x], L[bel[x]]) ;
}
res = res + query(1, 1, n, L[t], L[x]) ;
d[++ tot] = intv(L[x], L[t]) ;
int mid = tot + 1 ;
for ( ; bel[y] != bel[t] ; y = fa[bel[y]]) {
res = res + query(1, 1, n, L[bel[y]], L[y]) ;
d[++ tot] = intv(L[bel[y]], L[y]) ;
}
if (y != t) {
res = res + query(1, 1, n, L[t] + 1, L[y]) ;
d[++ tot] = intv(L[t] + 1, L[y]) ;
}
if (mid < tot) {
reverse(d + mid, d + tot + 1) ;
}
if ((res.cov[0] & 1) && (res.cov[1] & 1)) {
puts("No") ;
continue ;
}
puts("Yes") ;
intv inp = intv(1, 1) ;
inp = Solve(inp, res.cov[0] / 2, 0) ;
inp = Solve(inp, res.cov[1] / 2, 1) ;
if (res.cov[0] & 1) {
inp = Solve(inp, 1, 0) ;
}
if (res.cov[1] & 1) {
inp = Solve(inp, 1, 1) ;
}
inp = Solve(inp, res.cov[1] / 2, 1) ;
inp = Solve(inp, res.cov[0] / 2, 0) ;
}
return 0 ;
}
C.海棠溪
得分:17 分
预期:61 分
其实是个dp题,至于为什么出在数据结构考试中,你一会儿就知道了。(ヾ(>Д<;))))….. 逃
深搜17分
#include
using namespace std ;
const int inf = INT_MAX/2 ;
int n,T,A,B,ans ;
int a[100010] ;
void dfs(int k,int A,int B,int sum){
if (sum>ans) return ;
if (k==T+1){
if (ans>sum) ans=sum ;
return ;
}
dfs(k+1,a[k],B,sum+(abs(a[k]-A))) ;
dfs(k+1,A,a[k],sum+(abs(a[k]-B))) ;
}
int main(){
scanf("%d%d%d%d",&n,&T,&A,&B);
for (int i=1;i<=T;i++) scanf("%d",&a[i]) ;
ans=inf ;
dfs(1,A,B,0);
cout<
考虑dp
dp[i][j] d p [ i ] [ j ] 表示现在处理到第i 个人,另一朵花在第j 个人手上的答
案。
dp[i][j]+abs(xj−xi+1) d p [ i ] [ j ] + a b s ( x j − x i + 1 ) 更新 dp[i+1][i] d p [ i + 1 ] [ i ]
dp[i][j]+abs(xi−xi+1) d p [ i ] [ j ] + a b s ( x i − x i + 1 ) 更新 dp[i+1][j] d p [ i + 1 ] [ j ]
这样要过 Subtask3 S u b t a s k 3 ,会 MLE M L E ,滚动就61分
感谢XRY大佬
#include
using namespace std ;
const int inf = 0x3f3f3f3f ;
const int N = 200000 ;
int n,T,A,B,ans ;
int DP[N],dp[N],a[N],b[N] ;
int main(){
scanf("%d%d%d%d",&n,&T,&A,&B) ;
for (int i=1;i<=T;i++) scanf("%d",&a[i]) ;
memset(dp,0x3f,sizeof(dp)) ;
memset(DP,0x3f,sizeof(DP)) ;
DP[A]=abs(a[1]-B) ;
DP[B]=abs(a[1]-A) ;
for (int i=2;i<=T;i++){
for (int j=1;j<=n;j++){
dp[j]=min(dp[j],DP[j]+abs(a[i-1]-a[i])) ;
dp[a[i-1]]=min(dp[a[i-1]],DP[j]+abs(j-a[i])) ;
}
memcpy(DP,dp,sizeof(DP)) ;
memset(dp,0x3f,sizeof(dp)) ;
}
ans=inf;
for (int i=1;i<=n;i++) ans=min(ans,DP[i]) ;
printf("%d\n",ans) ;
}
Subtask 4:39 分
1 考虑用一个数据结构维护一下 fi f i 。
2 对于大部分的位置相当于是区间加了一个 |xi−xi+1| | x i − x i + 1 | 。对于 i−1 i − 1 的位置要通过上一行整行来计算。
3 把绝对值拆掉处理方法:将第二维的含义修改成位置,这样加和减所对应的就是连续的区间了。
4 对于 f?,i−xi f ? , i − x i 及 f?,i+xi f ? , i + x i 分别维护。查询两次即可得到关于 fi,i−1 f i , i − 1 的答案。单点修改一下即可。
5 时间复杂度 O(Tlogn) O ( T l o g n ) 。
此为mjy0724 的 标算
#include
#include
#include
#include
#include
typedef long long ll ;
#define rep(i, a, b) for (int i = a; i <= b; ++ i)
const int N = 2e5 + 5 ;
const ll inf = 1e17 + 7 ;
using namespace std ;
int n, m, A, B, x[N] ;
ll bit[2][2][N], dist[N], f[2][N] ;
void put(int cx, int cy, int x, ll y) {
for ( ; x <= n ; x += x & (- x)) bit[cx][cy][x] = min(bit[cx][cy][x], y) ;
}
ll get(int cx, int cy, int x) {
ll res = inf ;
for ( ; x ; x -= x & (- x)) res = min(res, bit[cx][cy][x]) ;
return res ;
}
int main() {
scanf("%d%d%d%d", &n, &m, &A, &B) ;
rep(i, 1, m) scanf("%d", &x[i]) ;
rep(i, 0, 1) rep(j, 0, 1) rep(k, 1, n) bit[i][j][k] = inf ;
rep(i, 2, m) dist[i] = dist[i - 1] + abs(x[i] - x[i - 1]) ;
f[0][0] = abs(B - x[1]), f[1][0] = abs(A - x[1]) ;
put(0, 0, A, f[0][0] - dist[1] - A), put(0, 1, n - A + 1, f[0][0] - dist[1] + A) ;
put(1, 0, B, f[1][0] - dist[1] - B), put(1, 1, n - B + 1, f[1][0] - dist[1] + B) ;
rep(i, 1, m - 1) {
f[0][i] = min(get(1, 0, x[i + 1]) + dist[i] + x[i + 1], get(1, 1, n - x[i + 1] + 1) + dist[i] - x[i + 1]) ;
f[1][i] = min(get(0, 0, x[i + 1]) + dist[i] + x[i + 1], get(0, 1, n - x[i + 1] + 1) + dist[i] - x[i + 1]) ;
put(0, 0, x[i], f[0][i] - dist[i + 1] - x[i]), put(0, 1, n - x[i] + 1, f[0][i] - dist[i + 1] + x[i]) ;
put(1, 0, x[i], f[1][i] - dist[i + 1] - x[i]), put(1, 1, n - x[i] + 1, f[1][i] - dist[i + 1] + x[i]) ;
}
ll ans = inf ;
rep(i, 0, m - 1) ans = min(ans, min(f[0][i], f[1][i]) + dist[m] - dist[i + 1]) ;
printf("%lld\n", ans) ;
return 0 ;
}
还有Smy 巨佬%%%orzorz 的 fhq−treap f h q − t r e a p %%%%代码(太巨了)
#include
#include
#include
#include
#define int long long
using namespace std;
int f[2000005],sum[2000005],g[2000005];
int a[2000005],n,T,A,B,minl,Root,tot;
struct node{
int rch,lch,big,sma,val,key,bh;
}t[2000005];
int seed=233;
int Rand(){
return seed=seed*49271ll%2147483647;
}
void update(int now){
int bh=t[now].bh;
t[now].big=g[bh]-sum[bh+1]+a[bh];
t[now].sma=g[bh]-sum[bh+1]-a[bh];
if(t[now].lch){
t[now].big=min(t[now].big,t[t[now].lch].big);
t[now].sma=min(t[now].sma,t[t[now].lch].sma);
}
if(t[now].rch){
t[now].big=min(t[now].big,t[t[now].rch].big);
t[now].sma=min(t[now].sma,t[t[now].rch].sma);
}
}
void split(int now,int &a,int &b,int k){
if(now==0){
a=b=0;
return;
}
if(t[now].val<=k)
a=now,split(t[now].rch,t[a].rch,b,k);
else
b=now,split(t[now].lch,a,t[b].lch,k);
update(now);
}
void merge(int &now,int a,int b){
if(a==0||b==0){
now=a+b;
return;
}
if(t[a].keyelse
now=b,merge(t[now].lch,a,t[b].lch);
update(now);
}
signed main(){
scanf("%d%d%d%d",&n,&T,&A,&B);
for(int i=2;i<=T+1;i++)
scanf("%d",&a[i]);
a[0]=A;a[1]=B;
f[0]=0;
int now=0,last=1;
for(int i=2;i<=T+1;i++)
sum[i]=sum[i-1]+abs(a[i-1]-a[i]);
g[0]=0;
Root=1;tot++;
t[1].key=Rand();
t[1].val=a[0];
t[1].big=g[0]-sum[1]+a[0];
t[1].sma=g[0]-sum[1]-a[0];
t[1].lch=t[1].rch=0;
t[1].bh=0;
for(int i=2;i<=T+1;i++){
int x=1<<29,y=1<<29,z;
split(Root,x,y,a[i]);
f[i-1]=1ll<<50;
if(x)
f[i-1]=min(t[x].sma+a[i],f[i-1]);
if(y)
f[i-1]=min(t[y].big-a[i],f[i-1]);
f[i-1]+=sum[i-1];
g[i-1]=f[i-1];
z=++tot;
t[z].key=Rand();
t[z].val=a[i-1];
t[z].bh=i-1;
t[z].big=g[i-1]-sum[i]+a[i-1];
t[z].sma=g[i-1]-sum[i]-a[i-1];
t[z].lch=t[z].rch=0;
merge(Root,x,y);
split(Root,x,y,a[i-1]);
merge(x,x,z);
merge(Root,x,y);
}
minl=1ll<<50;
for(int i=0;i<=T;i++)
minl=min(g[i]+sum[T+1]-sum[i+1],minl);
cout<return 0;
}
END! E N D !
总结:第十名,主要是第3题没捞到44分,不然就第4的(don’t fake)
预期:203 分
加油,祝我 Rating R a t i n g Overflow O v e r f l o w ! (don’t fake)