最开始发现和之前听某个大佬讲的贪心很像,后来写了好几发都T了,甚至把原来的数组改成了VECTOR,后来发现似乎需要来一发二叉平衡树。。。
此时,队友波塞冬堆出来了最后一题,成功签到,我把题拿给队友,队友表示。。。这不是线段树吗。。。
于是下面是。。。赛中没整出来,但是赛后用自有“ 玄学树状数组 ”堆出来的题解。
设定1,我们要求的东西是:最小的机器启动数量前提下,最小的机器运行时间。
推论1,因而,在每个区间进行+1操作,之后统计最大的点的值即可
推论2,最短运行时间应当有,最后启动的机器,运行到最后,可以得到的时间。例如样例有:
1
3
1 3
4 6
2 5
编号:1 2 3 4 5 6 7
次数:1 2 2 2 1 0 0
如上,在第第一小时,器一台机器启动,在第二小时,第二台机器启动,在第5小时,其中一台机器结束,在第六小时,两台机器都结束。
于是,认为最后结束的应该是最后启动的机器,于是,将【2,6)之间所有数字减一:
编号:1 2 3 4 5 6 7
次数:1 1 1 1 0 0 0
从而得到第二只机器运行时间为6-2(4小时)
之后,发现,此时只有一台机器在运作,因而,关掉这台机器:
编号:1 2 3 4 5 6 7
次数:0 0 0 0 0 0 0
第一台启动的机器运行时间为:5-1=4小时
于是,总运行时间和为8小时,启动机器数量为2小时。
AC代码如下:
#include<bits/stdc++.h> using namespace std; /* *常量MAXN用于设定树状数组的尺寸大小 */ const long long MAXN=300233; const long long INF=1e9+233; class TreeLikeArray { public: /* *数组c1用来储存A[i]-A[i-1]; */ long long c1[MAXN]; /* *数组c2用来储存(A[i]-A[i-1])*(i-1); *或认为用于储存(i-1)*c1[i]; *两种实现方式完全等价 */ long long c2[MAXN]; /* *树状数组的常规操作,参数要求传入数组并指明更新位置,以及更新参数。 *树状数组基础底层操作 */ void init() { memset(c1,0,sizeof(c1)); memset(c2,0,sizeof(c2)); } void add(long long array[],long long pos,long long key) { while(pos<MAXN) { array[pos]+=key; pos+=pos&(-pos); } } /* *特别树状数组单点更新操作,要求传入位置和参数 */ void add(long long pos,long long key) { add(c1,pos,key); add(c1,pos+1,-key); add(c2,pos,(pos-1)*key); add(c2,pos+1,-pos*key); } /* *特别树状数组多点更新操作,要求传入起始位置、终止位置和参数 *该操作将会使得[pos1,pos2]闭区间内所有元素得到更新 */ void add(long long pos1,long long pos2,long long key) { add(c1,pos1,key); add(c1,pos2+1,-key); add(c2,pos1,(pos1-1)*key); add(c2,pos2+1,-pos2*key); } /* *树状数组的常规操作,参数要求传入数组并指明求和位置 *树状数组基础底层操作 */ long long getSum(long long array[],long long pos) { long long ret=0; while(pos>0) { ret+=array[pos]; pos-=pos&(-pos); }return ret; } /* *从起始节点到目标节点闭区间求和[0,i] */ long long getSum(long long pos) { return pos*getSum(c1,pos)-getSum(c2,pos); } /* *求[pos1,pos2]闭区间内元素和 */ long long getSum(long long pos1,long long pos2) { return getSum(pos2)-getSum(pos1-1); } /* *求pos单个元素的值 */ long long getSingle(long long pos) { return getSum(pos,pos); } };TreeLikeArray t1; long long a[MAXN]; long long b[MAXN]; long long c[MAXN]; int n; long long mach[ MAXN]; long long mapp(long long key) { return lower_bound(c,c+2*n,key)-c+1; } void init() { t1.init(); // memset(mach,0,sizeof(mach)); cin>>n; for(int i=0;i<n;++i) { cin>>a[i]>>b[i]; c[i*2]=a[i]; c[i*2+1]=b[i]; mach[i]=0; } sort(c,c+2*n+1); for(int i=0;i<n;++i) { int aa=mapp(a[i]); int bb=mapp(b[i]); t1.add(aa,bb-1,1); } long long maxx=0; for(int i=1;i<2*n+23;++i) { int key=t1.getSingle(i); if(key>maxx)mach[key]=i,maxx=key; // cout<<key<<ends<<mach[key]<<endl; } // cout<<maxx<<" "; long long mm=maxx; long long pos=2*n+233; long long ans=0; while(maxx) { while(t1.getSingle(pos)<=0)pos--; // cout<<c[mach[maxx]-1]<<" checkpoint "<<c[pos]<<endl; t1.add(mach[maxx],pos,-1); ans+=c[pos]-c[mach[maxx]-1]; if(!mach[maxx-1])mach[maxx-1]=mach[maxx]; maxx--; } cout<<mm<<" "<<ans<<" "; } int main() { cin.sync_with_stdio(false); int t;cin>>t; for(int it=0;it<t;++it) init(); }