codeforces 2016-2017 NTUWFTSC E Lines Game

26 篇文章 0 订阅
10 篇文章 0 订阅

Consider the following game about removing N straight line segments on the plane. The segments are numbered from 1 to N. The i-th segment connects points (0, i) and (1, pi), where the numbers p1, p2, ..., pN are a permutation of numbers from 1 to N. Your are also given N positive integers v1, v2, ..., vN. On each step, you can select any segment i which is not removed yet, pay vi dollars, and then remove the i-th segment and all segments intersecting with it. Note that you MUST remove all segments which intersect with i-th segment.

The purpose of this game is to remove all segments while spending the minimum possible sum of dollars. Please answer how much you need to spend when you play the game with best strategy.

Input

The input consists of three lines. The first line contains an integer N. The second line consists of N integers p1, p2, ..., pN. The third line consists of N integer v1, v2, ..., vN.

  • 1 ≤ N ≤ 105
  •  is a permutation of 1, 2, ..., N
  • 1 ≤ vi ≤ 2 × 104
Output

Output only one number indicating the minimum possible sum of dollars required to remove all segments.

Examples
input
4
2 1 4 3
1 2 3 4
output
4
input
4
1 2 3 4
1 2 3 4
output
10
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

计算几何+思路~

我们把所有点极角排序一遍,然后扫描计算每个角对于答案的贡献。

数组又双叒叕开小了,我是不是也应该像柴神那样写个副标题了2333


#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

int n,ans,b[100001],t,x;

struct node{
	int x,y;
}a[100002];

node operator - (node u,node v)
{
	return (node){u.x-v.x,u.y-v.y};
}

ll operator * (node u,node v)
{
	return (ll)u.x*v.y-(ll)u.y*v.x;
}

bool cmp(int u,int v)
{
	return a[u]*a[v]>0;
}

int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return x*f; 
}

int main()
{
	n=read();
	for(int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),b[i]=i;
	sort(b+1,b+n+1,cmp);a[0]=a[n];a[n+1]=a[1];
	for(int i=1,j=1;i<=n;i=j)
	{
		x=0;
		for(j=i;j<=n && a[b[i]]*a[b[j]]==0;j++)
		  if(a[b[j]]*a[b[j]-1]<=0 && a[b[j]]*a[b[j]+1]<0)
		  {
		  	if((a[b[j]-1]-a[b[j]])*(a[b[j]+1]-a[b[j]])<0) t--;
		  	else x--;
		  }
		  else if(a[b[j]]*a[b[j]-1]>0 && a[b[j]]*a[b[j]+1]>=0)
		  {
		  	if((a[b[j]-1]-a[b[j]])*(a[b[j]+1]-a[b[j]])>0) t++;
		  	else x++;
		  }
		ans=max(ans,t);t+=x;ans=max(ans,t);
	}
	printf("%d\n",ans+1);
	return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值