李超线段树WA11pts,AC on #1,#11能过样例求调
查看原帖
李超线段树WA11pts,AC on #1,#11能过样例求调
477821
toolong114514楼主2024/6/11 21:03
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
#define int long long
const int INF=2147483647;
const int N=1e6+10;
const int M=1e7+10;
struct node{
	int lson,rson,bst;
}tree[M];
struct ccf{
	int k,b;
}ln[N];
int cnt;
int root,tt;
void upd(int &pos,int num,int l,int r){
	if(!pos) pos=++tt;
	int mid=(l+r)/2;
	if((ln[tree[pos].bst].k==ln[num].k)&&(ln[tree[pos].bst].b==ln[num].b)) return;
	if(ln[tree[pos].bst].k*mid+ln[tree[pos].bst].b>ln[num].k*mid+ln[num].b) swap(tree[pos].bst,num);
	if(l==r) return;
	if(ln[num].k*l+ln[num].b<ln[tree[pos].bst].k*l+ln[tree[pos].bst].b) upd(tree[pos].lson,num,l,mid);
	if(ln[num].k*r+ln[num].b<ln[tree[pos].bst].k*r+ln[tree[pos].bst].b) upd(tree[pos].rson,num,mid+1,r);
}
int ask(int pos,int kk,int l,int r){
	if(!pos||kk<l||r<kk) return INF;
	if(l==r) return ln[tree[pos].bst].k*kk+ln[tree[pos].bst].b;
	int mid=(l+r)/2;
	return min(min(ask(tree[pos].lson,kk,l,mid),ask(tree[pos].rson,kk,mid+1,r)),ln[tree[pos].bst].k*kk+ln[tree[pos].bst].b);
}
int sum1[N],sum2[N],x[N],p[N],c[N];
int f[N];
int n,maxn;
signed main(){
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x[i]>>p[i]>>c[i];
		maxn=max(maxn,x[i]);
	}
	ln[0].b=INF;
	for(int i=1;i<=n;i++){
		sum1[i]=sum1[i-1]+p[i]*x[i];
		sum2[i]=sum2[i-1]+p[i];
	}
	ln[++cnt]={0,0};
	upd(root,cnt,0,maxn);
	for(int i=1;i<=n;i++){
		f[i]=ask(1,x[i],0,maxn)+sum2[i]*x[i]-sum1[i]+c[i];
		ln[++cnt]={-sum2[i],f[i]+sum1[i]+sum2[i]*x[i]};
		upd(root,cnt,0,maxn);
	}
	cout<<f[n];
	return 0;
}
2024/6/11 21:03
加载中...