UOJ10 UTR #1 pyx的难题(堆)

  显然优先级越高完成的越早,二分答案后用堆模拟就是O(nlog2n)的。考虑去一个log。先固定特殊题的优先级为最低,模拟一遍。这样在特殊题被扔过来到T的这段时间内,如果将特殊题的优先级提高至超过这其中某些时间段所做的题,这些时间就会空出来变为做特殊题。所以从小到大枚举优先级,直到空出来的时间恰好与做特殊题的时间相等即可。

  有一种类似但错误的思路是,将特殊题优先级提高至超过从特殊题被扔过来到做完特殊题的这段时间内的某些时间段所做的题,让以此提前的时间为做完特殊题的时间-T。但实际上在让特殊题提前的过程中,可能会使原本某些在其之前做完的题的被扔过来的时间变到做完特殊题之后。

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define N 300010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,c[N],s[N];
ll ans[N],T;
map<int,int> f;
struct data
{
	int t,s,p,i;
	bool operator <(const data&a) const
	{
		return p<a.p;
	}
}a[N];
bool cmp(const data&a,const data&b)
{
	return a.t<b.t;
}
priority_queue<data> q;
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	const char LL[]="%I64d\n";
#else
	const char LL[]="%lld\n";
#endif
	n=read();
	for (int i=1;i<=n;i++) a[i].t=read(),s[i]=a[i].s=read(),f[a[i].p=read()]=1,a[i].i=i;
	cin>>T;
	sort(a+1,a+n+1,cmp);
	bool flag=0;
	for (int i=1;i<=n;i++)
	{
		int lst=a[i-1].t;
		while (!q.empty()&&lst<a[i].t)
		{
			data x=q.top();q.pop();
			if (flag) c[x.i]+=min(min(T,1ll*a[i].t)-lst,1ll*x.s);
			if (a[i].t-lst>=x.s) lst+=x.s;
			else x.s-=a[i].t-lst,q.push(x),lst=a[i].t;
			if (lst>=T) {flag=0;break;}
		}
		if (lst>=T) {flag=0;break;}
		q.push(a[i]);if (a[i].p==-1) flag=1;
	}
	if (flag)
	{
		ll lst=a[n].t;
		while (!q.empty())
		{
			data x=q.top();q.pop();
			c[x.i]+=min(T-lst,1ll*x.s);
			lst+=x.s;if (lst>=T) break;
		}
	}
	sort(a+1,a+n+1);
	ll t=0;
	for (int i=1;i<=n;i++)
	{
		t+=c[a[i].i];
		if (t==a[1].s)
		{
			if (i==1) a[1].p=1;
			else a[1].p=a[i].p;
			break;
		}
	}
	while (f[a[1].p]) a[1].p++;
	cout<<a[1].p<<endl;
	sort(a+1,a+n+1,cmp);
	for (int i=1;i<=n;i++) a[i].s=s[a[i].i];
	while (!q.empty()) q.pop();
	for (int i=1;i<=n;i++)
	{
		int lst=a[i-1].t;
		while (!q.empty()&&lst<a[i].t)
		{
			data x=q.top();q.pop();
			if (a[i].t-lst>=x.s) ans[x.i]=lst+=x.s;
			else x.s-=a[i].t-lst,q.push(x),lst=a[i].t;
		}
		q.push(a[i]);
	}
	ll lst=a[n].t;
	while (!q.empty())
	{
		data x=q.top();q.pop();
		ans[x.i]=lst+=x.s;
	}
	for (int i=1;i<=n;i++) printf("%lld ",ans[i]);
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/Gloid/p/10702419.html