2025.6.22-2025.6.23做题记录
前言
中考一周年啊,能不能放我进去圆我数学和理综AK梦啊啊啊啊啊啊的`(>﹏<)′
推积木KLO
如果 \(f_{i,j}\)表示第 \(i\) 个方块,删除 \(j\) 个的最优解,感觉上没法优化(因为是个背包),所以扔了。
换一个 \(f_i\) 表示第 \(i\) 个方块必须在位置上时的最优解,那么 \(f_{a_i}=\max f_{a_j}+1\) 转移。
问题是转移的条件。
转移条件如下:\(i>j,a_i>a_j,a_i-a_j\le i-j\) 。其实是二维偏序。
移项得到 \(i-a_i\ge j-a_j\) 按照 \(i-a_i\) 升序排序,再用树状数组限制一维,同时转移。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int M=1e6+10;
int n;
struct BIT{
#define lowbit(i) i&-i
int tr[M];
void update(int x,int k){
if(!x) return ;
for(int i=x;i<=n;i+=lowbit(i)){
tr[i]=max(k,tr[i]);
}
}
int query(int x){
int res=0;
for(int i=x;i;i-=lowbit(i)){
res=max(tr[i],res);
}
return res;
}
}T;
struct node{
int x,id;
}a[N];
bool cmp(node a,node b){
return (a.id-a.x==b.id-b.x) ? a.id<b.id : a.id-a.x<b.id-b.x;
}
int res=0,ans;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].x;
a[i].id=i;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++){
if(a[i].id-a[i].x<0) continue;
res=T.query(a[i].x-1)+1;
ans=max(res,ans);
T.update(a[i].x,res);
}
cout << ans;
return 0;
}
跳跳棋
只要发现题目中的跳跃是类似一棵二叉树时,我们已经做完80%了。
树上的节点是一个三元组表示三个点的位置。
中间点向两侧跳 是儿子,两侧只有一个点能向中间跳 是父亲节点。
我们把树建出来,根节点相同就代表能跳一起,最少步数就是 LCA。
关键是有 1e9 的数据范围,所以我们需要减少建树这一步骤。
发现如果两个点来回翻滚,另一个点不动的过程是固定的,这一步我们拿除法做。
后续正常的 LCA 即可。实现类似倍增求 LCA。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int a[4],b[4];
struct node{
int a,b,c,tot;
}A,B;
bool cmp(node a,node b){
return a.tot<b.tot;
}
void dfs(int a,int b,int c){
int tot=0;
while(1){
int d1=b-a,d2=c-b;
if(d1==d2) break;
if(d1<d2){
int d3=(d2-1)/d1;
tot+=d3;
a+=d1*d3;
b+=d1*d3;
}else{
int d3=(d1-1)/d2;
tot+=d3;
c-=d2*d3;
b-=d2*d3;
}
}
if(A.a||A.b) B={a,b,c,tot};
else A={a,b,c,tot};
}
bool check(int T,int a,int b,int c,int x,int y,int z){
int tot=T;
while(tot){
int d1=b-a,d2=c-b;
if(d1==d2) break;
if(d1<d2){
int d3=min((d2-1)/d1,tot);
tot-=d3;
a+=d1*d3;
b+=d1*d3;
}else{
int d3=min((d1-1)/d2,tot);
tot-=d3;
c-=d2*d3;
b-=d2*d3;
}
}
tot=T;
while(tot){
int d1=y-x,d2=z-y;
if(d1==d2) break;
if(d1<d2){
int d3=min((d2-1)/d1,tot);
tot-=d3;
x+=d1*d3;
y+=d1*d3;
}else{
int d3=min((d1-1)/d2,tot);
tot-=d3;
z-=d2*d3;
y-=d2*d3;
}
}
return a==x && b==y && c==z;
}
int ans1,ans2;
int main(){
cin>>a[1]>>a[2]>>a[3]>>b[1]>>b[2]>>b[3];
sort(a+1,a+1+3);sort(b+1,b+1+3);
dfs(a[1],a[2],a[3]);
dfs(b[1],b[2],b[3]);
if(A.a!=B.a || A.b!=B.b || A.c!=B.c){
cout << "NO";
return 0;
}
if(A.tot<B.tot){
swap(A.a,B.a);
swap(A.b,B.b);
swap(A.c,B.c);
swap(A.tot,B.tot);
swap(a,b);
}
int tot=A.tot-B.tot;
ans1=tot;
while(tot){
int d1=a[2]-a[1],d2=a[3]-a[2];
if(d1==d2) break;
if(d1<d2){
int d3=min((d2-1)/d1,tot);
tot-=d3;
a[1]+=d1*d3;
a[2]+=d1*d3;
}else{
int d3=min((d1-1)/d2,tot);
tot-=d3;
a[3]-=d2*d3;
a[2]-=d2*d3;
}
}
int l=0,r=B.tot;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid,a[1],a[2],a[3],b[1],b[2],b[3])){
ans2=mid;
r=mid-1;
}else{
l=mid+1;
}
}
cout<<"YES\n" << ans1+ans2*2;
return 0;
}

浙公网安备 33010602011771号