【题解】CJOI2019 Oct 17 GZYZSY Round Day2 简要题解

【题解】CJOI2019 Oct 17 GZYZSY Round Day2 简要题解

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define getchar() (__c==__ed?(__ed=__buf+fread(__c=__buf,1,1<<18,stdin),*__c++):*__c++)


using namespace std;  typedef long long ll;   char __buf[1<<18],*__c=__buf,*__ed=__buf; 
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(!isdigit(c))f|=c==45,c=getchar();
      while(isdigit(c)) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}

const ll mod=20190816170251ll;
const int maxn=2e5+5;
vector<int> data[maxn];
pair<int,int> rnk[maxn];
int arc[maxn],n,m;
ll ans;
struct E{
      ll sum; int x,y;
      inline bool operator <(const E&a)const{return sum<a.sum;}
};
template<class qaq>
struct HEAP{
      qaq data[maxn*3];
      int cnt;
      HEAP(){cnt=0;}
      inline void up(const int&pos){
        for(int t=pos;t>>1;t>>=1)
          if(data[t>>1]<data[t]) swap(data[t],data[t>>1]);
          else return;
      }
      inline void down(const int&pos){
        for(int t=pos,k;(t<<1)<=cnt;t=k){
          k=t<<1;
          if(k<cnt&&data[k]<data[k|1]) k|=1;
          if(data[t]<data[k])swap(data[t],data[k]);
          else return;
        }
      }
      inline void push(const qaq&tag){data[++cnt]=tag; up(cnt);}
      inline void pop(){swap(data[1],data[cnt--]);down(1);}
      inline const qaq&top(){return data[1];}
};
HEAP<E> q;

int main(){
#ifndef ONLINE_JUDGE
      freopen("contain.in","r",stdin);
      freopen("contain.out","w",stdout);
#endif
      n=qr(); m=qr();
      for(int t=1;t<=n;++t){
        for(int g=qr();g;--g)
          data[t].push_back(qr());
        sort(data[t].begin(),data[t].end(),[&](int x,int y){return x>y;});
        ans=ans+data[t][0];
        if(data[t].size()==1) data[t].clear(),--t,--n;
      }
      sort(data+1,data+n+1,[&](const vector<int>&a,const vector<int>&b){return a[0]-a[1]<b[0]-b[1];});
      --m;
      q.push({ans-data[1][0]+data[1][1],1,1});
      while(m--){
        auto g=q.top();
        int x=g.x,y=g.y;
        q.pop();
        ans=(ans*23333+g.sum)%mod;
        if(y+1<data[x].size())
          q.push({g.sum-data[x][y]+data[x][y+1],x,y+1});
        if(x<n)
          q.push({g.sum-data[x+1][0]+data[x+1][1],x+1,1});
        if(x<n&&y==1)
          q.push({g.sum+data[x][0]-data[x][1]-data[x+1][0]+data[x+1][1],x+1,1});
      }
      printf("%lld\n",ans);
      return 0;
}

先放代码

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>


using namespace std;  typedef long long ll;
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(!isdigit(c))f|=c==45,c=getchar();
      while(isdigit(c)) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}

const int maxn=2e3+5;
int data[maxn];

namespace sol{
      ll dp[maxn][maxn];
      int stk[maxn][maxn];
      int n,m,len;
      inline int divd(int*x,ll*y,const ll&tag){
        if(*x<=1) return *x;
        int len=*x;
        if(y[x[2]]-y[x[1]]>=tag*(x[2]-x[1])) return 1;
        if(y[x[len]]-y[x[len-1]]<=tag*(x[len]-x[len-1])) return len;
        int l=2,r=len-1,mid;
        do{
          mid=(l+r)>>1;
          if(y[x[mid]]-y[x[mid-1]]<=tag*(x[mid]-x[mid-1])) l=mid+1;
          else r=mid-1;
        }while(l<=r);
        return r;
      }
      inline void init(const int&a,const int&b){
        n=a; m=b;
        for(int t=1;t<=n;++t) data[t]=qr();
        sort(data+1,data+n+1,[&](const int&a,const int&b){return a>b;});
        memset(dp,0x3f,sizeof dp);
        memset(stk,0,sizeof stk);
        ll ans=dp[0][0];
        dp[0][0]=0;
        for(int t0=1;t0<=n;++t0){
          dp[1][t0]=1ll*t0*data[t0];
          for(int t=2;t<=m;++t){
            int g=divd(stk[t-1],dp[t-1],data[t0]);
            if(g) dp[t][t0]=dp[t-1][stk[t-1][g]]+1ll*(t0-stk[t-1][g])*data[t0];
          }
          ans=min(ans,dp[m][t0]);
          for(int t=1;t<m;++t){
            if(dp[t][t0]<=ans){
                  int*x=stk[t]; ll*y=dp[t];
                  while(*x&&y[x[*x]]>=ans) --*x;
                  while(*x>=2&&(long double)(y[x[*x]]-y[x[*x-1]])*(t0-x[*x-1])>=(long double)(y[t0]-y[x[*x-1]])*(x[*x]-x[*x-1])) --*x;
                  x[++*x]=t0;
            }
          }
        }
        printf("%lld\n",ans);
      }
}

int main(){
#ifndef ONLINE_JUDGE
      freopen("protect.in","r",stdin);
      freopen("protect.out","w",stdout);
#endif
      int T=qr(),a,b;
      while(T--) a=qr(),b=qr(),sol::init(a,b);
      return 0;
}

猜你喜欢

转载自www.cnblogs.com/winlere/p/11695765.html