QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#379407#8572. Passing Gameucup-team3396#TL 0ms13900kbC++144.1kb2024-04-06 17:27:152024-04-06 17:27:17

Judging History

你现在查看的是最新测评结果

  • [2024-04-06 17:27:17]
  • 评测
  • 测评结果:TL
  • 用时:0ms
  • 内存:13900kb
  • [2024-04-06 17:27:15]
  • 提交

answer

#include <bits/stdc++.h>
#define int long long
#define double long double
#define MOD1 39989
#define MOD2 1000000000
#define MAXT 40000
using namespace std;
typedef pair<double, int> pdi;

const double eps = 1e-9;

int cmp(double x, double y) {
  if (x - y > eps) return -1;
  if (y - x > eps) return 1;
  return 0;
}

struct node{
	int x,s,tag;
}a[1000005];

struct line {
  double k, b;
} p[2000005];

int s[2000005];
int cnt;

double calc(int id, int d) { return p[id].b + p[id].k * a[d].x; }

void add(int x0, int y0, int x1, int y1) {
	// cout<<x0<<" "<<y0<<" "<<x1<<" "<<y1<<"\n";
  cnt++;
  if (x0 == x1)  // 特判直线斜率不存在的情况
    p[cnt].k = 0, p[cnt].b = min(y0, y1);
  else
    p[cnt].k = 1.0 * (y1 - y0) / (x1 - x0), p[cnt].b = y0 - p[cnt].k * x0;
}

void upd(int root, int cl, int cr, int u) {  // 对线段完全覆盖到的区间进行修改
  int &v = s[root], mid = (cl + cr) >> 1;
  int bmid = cmp(calc(u, mid), calc(v, mid));
  if (bmid == 1 || (!bmid && u < v)) swap(u, v);
  int bl = cmp(calc(u, cl), calc(v, cl)), br = cmp(calc(u, cr), calc(v, cr));
  if (bl == 1 || (!bl && u < v)) upd(root << 1, cl, mid, u);
  if (br == 1 || (!br && u < v)) upd(root << 1 | 1, mid + 1, cr, u);
}

void update(int root, int cl, int cr, int l, int r,
            int u) {  // 定位插入线段完全覆盖到的区间
  if (l <= cl && cr <= r) {
    upd(root, cl, cr, u);
    return;
  }
  int mid = (cl + cr) >> 1;
  if (l <= mid) update(root << 1, cl, mid, l, r, u);
  if (mid < r) update(root << 1 | 1, mid + 1, cr, l, r, u);
}

pdi pmax(pdi x, pdi y) {  // pair max函数
  if (cmp(x.first, y.first) == -1)
    return y;
  else if (cmp(x.first, y.first) == 1)
    return x;
  else
    return x.second < y.second ? x : y;
}

pdi query(int root, int l, int r, int d) {  // 查询
  if (r < d || d < l) return {1e18, 0};
  int mid = (l + r) >> 1;
	// cout<<root<<" "<<l<<" "<<r<<" "<<d<<"\n";
  double res = calc(s[root], d);
  if (l == r) return {res, s[root]};
  return pmax({res, s[root]}, pmax(query(root << 1, l, mid, d),
                                   query(root << 1 | 1, mid + 1, r, d)));
}

// int main() {
//   ios::sync_with_stdio(false);
//   int n, lastans = 0;
//   cin >> n;
//   while (n--) {
//     int op;
//     cin >> op;
//     if (op == 1) {
//       int x0, y0, x1, y1;
//       cin >> x0 >> y0 >> x1 >> y1;
//       x0 = (x0 + lastans - 1 + MOD1) % MOD1 + 1,
//       x1 = (x1 + lastans - 1 + MOD1) % MOD1 + 1;
//       y0 = (y0 + lastans - 1 + MOD2) % MOD2 + 1,
//       y1 = (y1 + lastans - 1 + MOD2) % MOD2 + 1;
//       if (x0 > x1) swap(x0, x1), swap(y0, y1);
//       add(x0, y0, x1, y1);
//       update(1, 1, MOD1, x0, x1, cnt);
//     } else {
//       int x;
//       cin >> x;
//       x = (x + lastans - 1 + MOD1) % MOD1 + 1;
//       cout << (lastans = query(1, 1, MOD1, x).second) << endl;
//     }
//   }
//   return 0;
// }

bool cmpp(node A,node B){
	return A.x<B.x;
}
int dp[1000005],f[1000005],g[1000005];
int solve(){
	int n,k; cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i].x;
	for(int i=1;i<=n;i++) cin>>a[i].s,a[i].tag=0;
	a[1].tag=1;
	a[n].tag=2;
	sort(a+1,a+n+1,cmpp);
	for(int i=1;i<=n;i++) dp[i]=1e18;
	for(int i=1;i<=n;i++) if(a[i].tag==1) dp[i]=0;
	for(int i=1;i<=4*n;i++) s[i]=0;
	p[0].b=1e18;
	for(int i=0;i<=min(k,30ll);i++){
		for(int j=1;j<=n;j++) f[j]=g[j]=1e18;
		for(int j=1;j<=4*n;j++) p[j].k=p[j].b=0,s[j]=0;
		cnt=0;
		for(int j=1;j<=n;j++){
			f[j]=min(dp[j],(int)query(1,1,n,j).first);
			// cout<<f[j]<<" ";
			add(a[1].x,f[j]-(a[j].x-a[1].x)*a[j].s,a[n].x,f[j]+(a[n].x-a[j].x)*a[j].s);
			update(1,1,n,1,n,cnt);
		}
		for(int j=1;j<=4*n;j++) p[j].k=p[j].b=0,s[j]=0;
		cnt=0;
		for(int j=n;j>=1;j--){
			g[j]=min(dp[j],(int)query(1,1,n,j).first);
			// cout<<g[j]<<" ";
			add(a[1].x,f[j]+(a[j].x-a[1].x)*a[j].s,a[n].x,f[j]-(a[n].x-a[j].x)*a[j].s);
			update(1,1,n,1,n,cnt);
		}
		for(int j=1;j<=n;j++) dp[j]=min(f[j],g[j]);//cout<<dp[j]<<" ";
		// cout<<"\n";
	}
	for(int i=1;i<=n;i++) if(a[i].tag==2) return dp[i];
}

signed main(){
	int t; cin>>t;
	while(t--) cout<<solve()<<"\n";
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 13900kb

input:

2
4 2
3 2 1 6
3 1 1 3
2 0
1 2
1 2

output:

7
1

result:

ok 2 number(s): "7 1"

Test #2:

score: -100
Time Limit Exceeded

input:

1
300000 204334
809492393 304618667 173130445 377106790 364888630 949045125 622060683 557772818 216607577 848817467 862855568 507840723 120816645 639713488 741781998 682531787 685261161 601686403 355792373 162819930 710057718 234560726 998604853 678957602 485413982 855985802 109303681 979706626 4822...

output:


result: