一个环形路上不同位置种了一些苹果,每次最多拿k个,问从0点出发取完苹果回到0点最短的路程,大概就是左右半边的环先进行一次贪心,最后走整个环最多只有一次,因为最后左右两边的数量都是小于k的(若大于等于k,是可以通过半个环取走k个的),然后走了一次整个环,有一个半环一定已经被取完了,所以最后剩下的那半个环也不需要再走一遍整个环了
#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include<stdio.h> #include<string.h> #include<vector> #include<algorithm> #include<cmath> #include<map> #include<queue> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1 | 1 #define lowbit(x) x&(-x) using namespace std; const int N=5e5+10; long long INF=-1e15; const int MOD=1e9+7; int T,n,m,k,l; long long ans; int sum; int L[N],R[N]; long long ll[N],rr[N]; int sl,sr; void solve(){ ll[0]=rr[0]=0; for(int i=1;i<=sl;i++){ if(i<=k) ll[i]=L[i]*2; else ll[i]=ll[i-k]+L[i]*2; } for(int i=1;i<=sr;i++){ if(i<=k) rr[i]=R[i]*2; else rr[i]=rr[i-k]+R[i]*2; } } int main() { #ifndef ONLINE_JUDGE freopen("aaa","r",stdin); #endif int T; scanf("%d",&T); while(T--){ scanf("%d%d%d",&l,&n,&k); sum=0;sl=sr=0; for(int i=1;i<=n;i++){ int pos,num; scanf("%d%d",&pos,&num); if(pos<=l/2){ for(int j=0;j<num;j++) L[++sl]=pos; } else { for(int j=0;j<num;j++) R[++sr]=l-pos; } } sort(L+1,L+sl+1); sort(R+1,R+sr+1); solve(); long long res=0x3f3f3f3f3f3f3f; res=min(res,ll[sl]+rr[sr]); for(int i=0;i<=k;i++){ res=min(res,l+ll[sl-i]+rr[max(0,sr-(k-i))]); } printf("%I64d\n",res); } return 0; }