P7302 免费的馅饼 关于按照两个关键字树状数组优化转移正确性的疑问
  • 板块题目总版
  • 楼主wind_whisper
  • 当前回复3
  • 已保存回复3
  • 发布时间2021/9/14 00:05
  • 上次更新2023/11/4 06:50:51
查看原帖
P7302 免费的馅饼 关于按照两个关键字树状数组优化转移正确性的疑问
449265
wind_whisper楼主2021/9/14 00:05

原题
蒟蒻过掉了本题,但感觉并没有完全理解...
题解的做法大同小异,根据 i 从 j 合法转移要求的条件: 2ti+pi<=2tj+pj(pi<=pj)2*t_i+p_i<=2*t_j+p_j(p_i<=p_j) 2tipi<=2tjpj(pi>pj)2*t_i-p_i<=2*t_j-p_j(p_i>p_j)

然后按照第一个式子关键字排序,对第二个式子对应的关键字离散化后利用树状数组优化进行转移(类似于顺序对的方法)
然鹅蒟蒻我推到上面那两个个式子就蚌住了qwq
上面那两个式子得以成立的前提似乎是: ti>=tjt_i>=t_j 这是推导过程中默认的条件,不然t也得套绝对值进行讨论了
但是按照上面第一个关键字排序后,似乎不能保证t_i>=t_j了
举个例子,t1=5,p1=1,t2=6,p2=2
两个关键字比完1都比2小
按本算法也就是1可以从2转移过来 但显然时间t1<t2,时间不可能倒流这个转移时非法的
但这个数据卡不掉,因为实际上应该是2从1转移过来,结果是一样的
以本做法能AC来看,这种做法尽管转移的意义可能会与实际不同,但结果应该都是没问题的
但我还是对这道题的不用讨论t先后的原因不很理解
希望各位大佬能指点一下本题是如何避免对t的绝对值的讨论的
谢谢!OvO
(附迷惑之下写出的AC代码)

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+100;
#define ll long long
#define I register int
ll read(){
	ll x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
	return x*f;
} 
int n;
struct node{
	int pl,t,v;
	bool operator < (const node y)const{return 2*t+pl<2*y.t+y.pl;}
}p[N];
int q[N],cnt;
int f[N];
void add(int x,int v){
	for(;x<=cnt;x+=x&-x) f[x]=max(f[x],v);
}
int ask(int x){
	int res=0;
	for(;x;x-=x&-x) res=max(res,f[x]);
	return res;
}
int main(){
	int w=read();n=read();
	for(int i=1;i<=n;i++){
		p[i].t=read();p[i].pl=read();p[i].v=read();
		q[i]=2*p[i].t-p[i].pl;
	}
	sort(p+1,p+1+n);
	sort(q+1,q+1+n);
	cnt=unique(q+1,q+1+n)-q-1;
	for(int i=1;i<=n;i++){
		int o=lower_bound(q+1,q+1+cnt,2*p[i].t-p[i].pl)-q;
		add(o,ask(o-1)+p[i].v);
	}
	printf("%d",ask(cnt));
}
/*
*/
2021/9/14 00:05
加载中...