Submission #108034

#TimeUsernameProblemLanguageResultExecution timeMemory
108034dragonslayeritCake 3 (JOI19_cake3)C++14
0 / 100
100 ms8568 KiB
#include <cstdio> #include <vector> #include <algorithm> #include <queue> #include <cassert> #include <set> #include <stdint.h> #include <map> const int64_t INF=1e15+7; std::vector<std::pair<int,int> > cake; std::map<int,int> cps; int N,M; const int MAXN=1<<18; struct Node{ int cnt; int64_t sum; Node():cnt(0),sum(0){ } }st[MAXN*2]; void st_add(int i,int c,int64_t v){ //printf("st_add(%d,%d,%ld)\n",i,c,v); for(i+=MAXN;i>0;i>>=1){ st[i].cnt+=c; st[i].sum+=v; } } void st_insert(int x,int c){ //printf("st_insert(%d) x%d\n",x,c); st_add(cps[x],c,x*c); } int64_t st_sum(int w,int L,int R,int k){ assert(st[w].cnt>=k); if(st[w].cnt==k){ return st[w].sum; } int M=(L+R)/2; if(st[w<<1|1].cnt>=k){ return st_sum(w<<1|1,M,R,k); }else{ return st_sum(w<<1,L,M,k-st[w<<1|1].cnt)+st[w<<1|1].sum; } } void st_dump(); int64_t st_sum(int k){ int64_t sum=0,cnt=0; for(int i=MAXN-1;i>=0&&cnt<k;i--){ sum+=st[i+MAXN].sum; cnt+=st[i+MAXN].cnt; } assert(cnt==k); //st_dump(); //printf("st_sum(%d)=%ld\n",k,sum); assert(sum==st_sum(1,0,MAXN,k)); return st_sum(1,0,MAXN,k); } void st_dump(){ for(int i=0;i<2*MAXN;i++){ if(st[i].cnt) printf(" ST[%d](%d): %ld\n",i,st[i].cnt,st[i].sum); } } struct DataStruct{ std::multiset<int> low,high; int ll,rr;//(ll,rr) for elements, [ll,rr] for query int64_t high_sum; DataStruct():ll(0),rr(1),high_sum(0){ } void up(){ int x=*low.rbegin(); high_sum+=x; high.insert(x); low.erase(low.find(x)); } void down(){ int x=*high.begin(); high_sum-=x; low.insert(x); high.erase(high.begin()); } void balance(){ while(low.size()&&high.size()<M-2){ up(); } while(high.size()>M-2){ down(); } while(low.size()&&high.size()&&*low.rbegin()>*high.begin()){ up(); down(); } } void add(int i){ st_insert(cake[i].second,1); return; int64_t x=cake[i].second; low.insert(x); } void rem(int i){ st_insert(cake[i].second,-1); return; int64_t x=cake[i].second; auto it=low.find(x); if(it!=low.end()){ low.erase(it); }else{ it=high.find(x); assert(it!=high.end()); high_sum-=x; high.erase(it); } } int64_t query(int l,int r){ if(r-l+1<M) return -INF; while(ll>l) add(ll--); while(rr<r) add(rr++); while(ll<l) rem(++ll); while(rr>r) rem(--rr); return st_sum(M-2)+cake[l].second+cake[r].second;//+2LL*(cake[l].first-cake[r].first); balance(); assert(high.size()+low.size()==r-l-1); return high_sum+cake[l].second+cake[r].second+2LL*(cake[l].first-cake[r].first); } /* void dump(){ for(int64_t x:low) printf("%ld ",x); printf("|"); for(int64_t x:high) printf(" %ld",x); printf("\n"); } */ }ds; int64_t best=-INF; //find ans for (l,r), which must be in range [low,high] void solve(int l,int r,int low,int high){ if(r-l<=1) return; int m=(l+r)/2; int64_t max=-INF; int maxi=-1; for(int i=low;i<=high;i++){ int64_t res=ds.query(m,i); if(res>=max){ maxi=i; max=res; } } best=std::max(best,max); //printf("best with l=%ld: %ld\n",m,max); solve(l,m,low,maxi); solve(m,r,maxi,high); } int64_t brute(int64_t l,int64_t r){ if(r-l+1<M) return -INF; std::multiset<int> best; for(int64_t i=l+1;i<r;i++){ best.insert(cake[i].second); } while(best.size()>M-2){ best.erase(best.begin()); } assert(best.size()==M-2); best.insert(cake[l].second); best.insert(cake[r].second); int64_t sum=0;//2LL*(cake[l].first-cake[r].first); for(int64_t x:best){ sum+=x; } return sum; } int main(){ scanf("%d %d",&N,&M); for(int i=0;i<N;i++){ int V,C; scanf("%d %d",&V,&C); cake.push_back({C,V}); cps[V]; } { int last=0; for(auto& it:cps){ it.second=last++; } for(auto it:cps){ //printf("V=%d: %dyh\n",it.first,it.second); } } std::sort(cake.begin(),cake.end()); /* for(int l=0;l<N;l++){ for(int r=0;r<N;r++){ printf("%ld,%ld ",ds.query(l,r),brute(l,r)); } printf("\n"); } */ solve(-1,N,0,N-1); /* for(int l=0;l<N;l++){ for(int r=l;r<N;r++){ best=std::max(best,brute(l,r)); } } */ printf("%ld\n",best); //ds.query(0,N-1),ds.dump(); return 0; }

Compilation message (stderr)

cake3.cpp: In member function 'void DataStruct::balance()':
cake3.cpp:94:34: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     while(low.size()&&high.size()<M-2){
                       ~~~~~~~~~~~^~~~
cake3.cpp:97:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     while(high.size()>M-2){
           ~~~~~~~~~~~^~~~
In file included from /usr/include/c++/7/cassert:44:0,
                 from cake3.cpp:5:
cake3.cpp: In member function 'int64_t DataStruct::query(int, int)':
cake3.cpp:133:34: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     assert(high.size()+low.size()==r-l-1);
            ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
cake3.cpp: In function 'int64_t brute(int64_t, int64_t)':
cake3.cpp:173:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   while(best.size()>M-2){
         ~~~~~~~~~~~^~~~
In file included from /usr/include/c++/7/cassert:44:0,
                 from cake3.cpp:5:
cake3.cpp:176:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   assert(best.size()==M-2);
          ~~~~~~~~~~~^~~~~
cake3.cpp: In function 'int main()':
cake3.cpp:199:14: warning: variable 'it' set but not used [-Wunused-but-set-variable]
     for(auto it:cps){
              ^~
cake3.cpp:187:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d %d",&N,&M);
   ~~~~~^~~~~~~~~~~~~~~
cake3.cpp:190:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d %d",&V,&C);
     ~~~~~^~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...