zoukankan      html  css  js  c++  java
  • CF702F TShirts

    兄,被教育了。

    考虑按照值域按\(2^x\)分块。

    那么我们有\(log_2 n\)块。

    考虑一次操作时,我们进行的操作。

    我们一定会有\(log2_n - log_2 x\)块会同时操作。

    那么此时我们有\([log_2 x - 1,log_2x)\)这块。

    我们一个数每次都会跌落到下一块,只会有\(log\)次的跌落,显而易见的是小的一定先跌落。

    我们用\(set\)维护一个块,那么一次操作为\(O(log)\)

    那么为\(O(nlog^2n)\)

    #include <bits/stdc++.h>
    
    #define ll long long 
    #define N 200005
    
    int ans[N];
    
    int n,k;
    int a[N];
    
    int UID(int a) { return a == 0 ? 0 : 32 - __builtin_clz(a); }
    
    struct B{
    	std::set<std::pair<int,int> >A;
    	int S,C;//S = times,C = sum x
    	
    	inline void del(int c,std::set<std::pair<int,int> >::iterator it);
    	
    	inline void sub(int lim,int x){//对这个快操作,lim为该块下限 
    		if(A.size()){
    //			std::cout<<lim<<" "<<x<<std::endl;
    			int begin = A.begin() -> first - C;//最小值 
    			if(x <= begin){//整块操作 
    				S ++ ;
    				C += x;
    				//处理跌落块操作。
    				begin = A.begin() -> first - C;				
    				while(A.size() && begin < lim){
    					del(0,A.begin());			
    					if(A.size())		
    					begin = A.begin() -> first - C;
    				} 
    			}else{//暴力操作  
    				while(A.size() && x <= A.rbegin() -> first - C){
    					std::set<std::pair<int,int> >::iterator it = A.end();
    					it -- ;
    					ans[it -> second] ++ ;
    					del(x,it);
    				}
    			} 
    		}
    	} 
    	B(){S = C = 0;}
    	
    }T[50];//块维护 
    
    inline void add(int b,int i){
    	int I = UID(b);
    	ans[i] -= T[I].S;
    	std::pair<int,int>a;
    	a.first = b + T[I].C,a.second = i;
    	T[I].A.insert(a);
    }
    
    inline void B::del(int c,std::set<std::pair<int,int> >::iterator it){
    	int x = it -> first;
    	int i = it -> second;
    //	std::cout<<c<<" "<<x<<" "<<i<<std::endl;	
    	A.erase(it);
    	ans[i] += S;
    	add(x - c - C,i);
    }	
    
    struct L{
    	int c,q;
    }e[N];
    
    bool operator < (L a,L b){
    	return (a.q == b.q) ? a.c < b.c : a.q > b.q;
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i = 1;i <= n;++i)
    	scanf("%d%d",&e[i].c,&e[i].q);
    	std::sort(e + 1,e + n + 1); 
    	scanf("%d",&k);
    	for(int i = 1;i <= k;++i)
    	scanf("%d",&a[i]),add(a[i],i);
    	for(int i = 1;i <= n;++i){
    		for(int j = 1;j <= 31;++j)
    		T[j].sub(1ll << (j - 1),e[i].c);
    	}
    	for(int j = 1;j <= 31;++j){
    		std::set<std::pair<int,int> >::iterator it = T[j].A.begin();
    		while(it != T[j].A.end()){
    			ans[it -> second] += T[j].S;
    			it ++ ;
    		}
    	}
    	for(int i = 1;i <= k;++i)
    	std::cout<<ans[i]<<" "; 
    }
    
  • 相关阅读:
    毕业设计同学们的福利(将word表格导入PowerDesigner中实现快速创建PDM)
    (转载)彻底的理解:WebService到底是什么?
    Aptana常用快捷键总结
    解决nuxt中路由变化后vanlist触底不加载的问题
    vuepropertydecorator的装饰器及其功能(可能不全)
    前端基础复习篇DOM
    Docker如何制作镜像Dockerfile的使用
    接口测试及常用接口测试工具
    SVN快速入门3——整合eclipse(1)
    SVN快速入门1——SVN的安装及常用命令
  • 原文地址:https://www.cnblogs.com/dixiao/p/15621301.html
Copyright © 2011-2022 走看看