T1:数字比大小的本质是按(长度,字典序)比大小。
T2:首先发现单调性,二分答案,用堆模拟,$O(n\log^2 n)$。
第二个log已经没有什么可优化的了,但是第一个可以做到线性。
我们先将特殊题的p就当作是-1跑一边,设这个题的出现时间是tx,完成所需时间为sx,记录下每个题在[tx,T]上的出现时间。把所有题按优先级排序,可以发现如果找到了前i个满足出现时间之和为sx,那么这些时间区间正好可以被特殊题区间覆盖,找到这个i就确定了优先级,最后再模拟一遍即可。
有个很容易忽视的问题,就是一定要保证得到的i是能让px尽量小的,这样才可以在总时间相同的情况下使特殊题最后做完,从而保证特殊题的完成时间就是T而不是T之前。
当然按上述做法把优先级从低到高排序没有任何问题,但是如果从高到低排序最后相减就会出错了。
为了这个问题调了一整个下午。
1 #include<map> 2 #include<cstdio> 3 #include<queue> 4 #include<algorithm> 5 #define rep(i,l,r) for (int i=l; i<=r; i++) 6 typedef long long ll; 7 using namespace std; 8 9 const int N=300010; 10 const ll inf=1000000000000000000ll; 11 int n,pp,pos,s[N],sm[N]; 12 ll mx,S,T,Ed[N]; 13 struct P{ int t,s,p,id; }a[N]; 14 priority_queue<P>Q; 15 map<ll,bool>mp; 16 17 bool operator <(const P &a,const P &b){ return a.p<b.p; } 18 bool cmp(const P &a,const P &b){ return (a.t==b.t) ? a.p>b.p : a.t<b.t; } 19 bool cmp1(int x,int y){ return a[x].p<a[y].p; } 20 void F(int id,ll l,ll r){ 21 l=max(l,S); r=min(r,T); 22 if (r>l) sm[id]+=r-l; 23 } 24 25 int main(){ 26 scanf("%d",&n); mp[0]=1; 27 rep(i,1,n){ 28 scanf("%d%d%d",&a[i].t,&a[i].s,&a[i].p); 29 if (a[i].p==-1) S=a[i].t,pp=a[i].s; 30 mp[a[i].p]=1; a[i].id=i; 31 } 32 scanf("%lld",&T); 33 sort(a+1,a+n+1,cmp); 34 rep(i,1,n) s[i]=i; 35 sort(s+1,s+n+1,cmp1); 36 for (int i=1,j=1; i<=n; i=j){ 37 for (; a[j].t==a[i].t; j++) Q.push(a[j]); 38 ll tim=a[i].t,ed=a[j].t; 39 if (ed==0) ed=inf; 40 while (!Q.empty()){ 41 P x=Q.top(); Q.pop(); 42 if (tim+x.s<=ed){ 43 F(x.id,tim,tim+x.s); tim+=x.s; mx=max(mx,tim); 44 if (tim==ed) break; 45 }else { x.s-=ed-tim; F(x.id,tim,ed); mx=max(mx,ed); Q.push(x); break; } 46 } 47 } 48 ll res=0,ans=1; 49 while (mp.count(ans)) ans++; 50 rep(i,1,n){ 51 res+=sm[a[s[i]].id]; 52 if (res==pp){ 53 //printf("%lld %lld %d %lld\n",S,res,pp,T); 54 //printf("%d %d %d\n",a[s[i]].p,a[s[i+1]].p,a[s[i+2]].p); 55 ans=(~a[s[i]].p) ? a[s[i]].p : a[s[i-1]].p; 56 while (mp.count(ans)) ans++; 57 break; 58 } 59 } 60 rep(i,1,n) if (a[i].p==-1) { a[i].p=ans; break; } 61 while (!Q.empty()) Q.pop(); 62 for (int i=1,j=1; i<=n; i=j){ 63 for (; a[j].t==a[i].t; j++) Q.push(a[j]); 64 ll tim=a[i].t,ed=a[j].t; 65 if (ed==0) ed=inf; 66 while (!Q.empty()){ 67 P x=Q.top(); Q.pop(); 68 if (tim+x.s<=ed) Ed[x.id]=tim+x.s,tim+=x.s; 69 else { x.s-=ed-tim; Q.push(x); tim=ed; break; } 70 } 71 } 72 printf("%lld\n",ans); 73 rep(i,1,n) printf("%lld ",Ed[i]); 74 return 0; 75 }