神奇slope trick做法,求证明复杂度
查看原帖
神奇slope trick做法,求证明复杂度
524091
dami826楼主2025/8/5 13:16

思路就是直接用slope trick维护1e9的dp数组

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,q,p[10010],a[10010],b[10010],pl;
struct node{
	int l,val,k;
	bool operator <(const node o)const{
		return l<o.l;
	}
};
set<node> st;
signed main(){
	scanf("%lld",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld %lld %lld",&p[i],&a[i],&b[i]);
	}
	st.insert({0,0,1});
	for(int i=n;i>=1;i--){
//		for(auto aa=st.begin();aa!=st.end();aa++){
//			printf("aggggggggggggggg %lld %lld %lld\n",aa->l,aa->val,aa->k);
//		}
		set<node> tmp;
		tmp.clear();
		auto itt=st.upper_bound({a[i]-pl,0,0});
		itt--;
		while(itt!=st.end()&&itt->l+pl<=p[i]+a[i]){
			tmp.insert({max(itt->l-a[i]-b[i],-pl-b[i]),itt->val+(max(itt->l-a[i]-b[i],-pl-b[i])-itt->l+a[i]+b[i])*itt->k,itt->k});
//			printf("tmp insert %lld %lld %lld\n",max(itt->l-a[i]-b[i],-pl-b[i]),itt->val+(max(itt->l-a[i]-b[i],-pl-b[i])-itt->l+a[i]+b[i])*itt->k,itt->k);
			itt++;
		}
//		printf("pl -> %lld\n",pl+b[i]);
		if(p[i]<b[i]){
			auto aaa=*st.lower_bound({-pl,0,0});
			pl+=b[i];
			st.insert({p[i]-pl+1,aaa.val,0});
		}
		else{
			pl+=b[i];
			auto it=st.upper_bound({p[i]-pl+1,0,0});
//			printf("bbbbbbbb %lld %lld %lld\n",it->l,it->val,it->k);
			it--;
			if(it->l!=p[i]-pl+1){
				auto tt=(*it);
//				printf("aaaaaaaaaaaaaaa%lld %lld %lld %lld\n",tt.l,p[i]-pl+1,it->val,tt.k);
				st.erase(it);
				tt.val+=(p[i]-pl+1-tt.l)*tt.k;
				tt.l=p[i]-pl+1;
				st.insert(tt);
//				printf("insert %lld %lld %lld\n",tt.l,tt.val,tt.k);
			}
//			printf("clear < %lld\n",p[i]-pl+1);
			it=st.lower_bound({p[i]-pl+1,0,0});
			while(it!=st.begin()){
				it--;
				st.erase(it);
				it=st.lower_bound({p[i]-pl+1,0,0});
			}
		}
		for(auto ii=tmp.begin();ii!=tmp.end();ii++){
			st.insert(*ii);
		}
	}
	scanf("%lld",&q);
	for(int i=1;i<=q;i++){
		int x;
		scanf("%lld",&x);
		auto it=st.upper_bound({x-pl,0,0});
		it--;
		printf("%lld\n",it->val+(x-pl-it->l)*it->k);
	}
	return 0;
}
2025/8/5 13:16
加载中...