zoukankan      html  css  js  c++  java
  • 【题解】由乃打扑克

    由乃打扑克

    ( ext{Solution:})

    题目就是区间加,求区间第 (k) 小。这里没有用时间分治的做法。

    考虑每次修改的时候,如果遇到散块就暴力重构,整块打标记。

    询问的时候直接二分答案,整块里面用 lower_bound, 对于散块:

    如果我们暴力做,复杂度是错误的,这样是根号外面带了两个 (log.) 所以我们不能暴力处理。

    考虑直接把散块拉出来。但是,由于我们需要保证块内有序,所以我们需要排序,但如果使用 sort 这样排序复杂度和块大小有关,不好平衡。

    发现两个散块都是有序的,直接双指针归并合并。这样复杂度就是对的了。

    考虑修改的时候,同样对于散块重构的时候还是需要归并,同样的道理会使得复杂度爆炸。

    对于块长,本题中用了 (frac{n}{128}) 的大小卡了过去。当然这个块长严重不符合理论大小。

    学到的东西:

    • 复杂度平衡排序不能和块长有关系,否则平衡的复杂度会炸掉。

    • char obuf[1<<21],*O=buf;Fwrite(int x){if(x>9)Fwrite(x/10);*O++=x%10+'0';} fwrite(obuf,O-obuf,1,stdout) 超级快输

    *一种双指针写法 vector

    vector<pr>::iterator ll=vt.begin();
    	vector<pr>::iterator rr=pt.begin();
    	for(;ll!=vt.end()||rr!=pt.end();){
    		pr I,J;
    		if(ll==vt.end()&&rr==pt.end())break;
    		if(ll!=vt.end()) I=*ll;
    		else I=mk(100000000ll,100000000ll);
    		if(rr!=pt.end()) J=*rr;
    		else J=mk(100000000ll,100000000ll);
    		if((ll==vt.end())||(rr!=pt.end()&&J<I)){
    			Ans.push_back(J);
    			++rr;
    		}
    		else{
    			Ans.push_back(I);
    			++ll;
    		}
    	}
    
    #include<bits/stdc++.h>
    using namespace std;
    const int N=200010;
    const int SN=128;
    int n,m,a[N];
    char buf[1<<21],*p1=buf,*p2=buf;
    char obuf[1<<21],*O=obuf;
    void Fwrite(int x){
    	int fg=1;
    	if(x<0)x=-x,*O++='-';
    	if(x>9)Fwrite(x/10);
    	*O++=x%10+'0';
    }
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    inline int read() {
    	int s=0,w=1;
    	char ch=getchar();
    	while(!isdigit(ch)){
    		if(ch=='-')w=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch)){
    		s=s*10+ch-'0';
    		ch=getchar();
    	}
    	return s*w;
    }
    typedef pair<int,int> pr;
    #define mk make_pair
    #define fi first
    #define se second
    inline bool cmp(const pr&A,const pr&B){return A.fi<B.fi;}
    int B,id[N];
    vector<pr>bk[N];
    int tag[N];
    inline int Min(int x,int y){return x<y?x:y;}
    vector<pr> St(vector<pr> vec,int l,int r,int v){
    	vector<pr>vt;
    	vector<pr>pt;
    	vector<pr>Ans;
    	for(int i=0;i<(int)vec.size();++i){
    		if(vec[i].se>=l&&vec[i].se<=r){
    			pt.push_back(mk(vec[i].fi+v,vec[i].se));
    		}
    		else vt.push_back(mk(vec[i].fi,vec[i].se));
    	}
    	vector<pr>::iterator ll=vt.begin();
    	vector<pr>::iterator rr=pt.begin();
    	for(;ll!=vt.end()||rr!=pt.end();){
    		pr I,J;
    		if(ll==vt.end()&&rr==pt.end())break;
    		if(ll!=vt.end()) I=*ll;
    		else I=mk(100000000ll,100000000ll);
    		if(rr!=pt.end()) J=*rr;
    		else J=mk(100000000ll,100000000ll);
    		if((ll==vt.end())||(rr!=pt.end()&&J<I)){
    			Ans.push_back(J);
    			++rr;
    		}
    		else{
    			Ans.push_back(I);
    			++ll;
    		}
    	}
    	return Ans;
    }
    void change(int l,int r,int v){
    	if(id[l]!=id[r]){
    		bk[id[l]]=St(bk[id[l]],l,r,v);
    		bk[id[r]]=St(bk[id[r]],l,r,v);
    		for(int i=id[l]+1;i<id[r];++i)tag[i]+=v;
    		return;
    	}
    	bk[id[l]]=St(bk[id[l]],l,r,v);
    }
    vector<pr>obk;
    bool check(int l,int r,int v,int k){
    	int cnt=0;
    	for(int i=id[l]+1;i<id[r];++i){
    		int pos=lower_bound(bk[i].begin(),bk[i].end(),mk(v-tag[i],0))-bk[i].begin();
    		cnt+=pos;
    	}
    	int pos=lower_bound(obk.begin(),obk.end(),mk(v,0))-obk.begin();
    	cnt+=pos;
    	return cnt<k;
    }
    void query(int l,int r,int v){
    	if(v>(r-l+1)){
    		puts("-1");
    		return;
    	}
    	int L=-2e9,R=2e9;
    	int ans=-1;
    	obk.clear();
    	if(id[l]!=id[r]){
    		vector<pr>::iterator i=bk[id[l]].begin();
    		vector<pr>::iterator j=bk[id[r]].begin();
    		for(;i!=bk[id[l]].end()||j!=bk[id[r]].end();){
    			pr I=*i;
    			pr J=*j;
    			I.first+=tag[id[l]];
    			J.first+=tag[id[r]];
    			if((i==bk[id[l]].end())||(j!=bk[id[r]].end()&&J<I)){
    				if(J.se>=l&&J.se<=r)obk.push_back(J);
    				++j;
    			}
    			else {
    				if(I.se>=l&&I.se<=r)obk.push_back(I);
    				++i;
    			}
    		}
    	}
    	else{
    		for(int i=0;i<Min(B,(int)bk[id[l]].size());++i){
    			pr X=bk[id[l]][i];
    			X.first+=tag[id[l]];
    			if(bk[id[l]][i].se>=l&&bk[id[l]][i].se<=r)obk.push_back(X);
    		}
    	}
    	while(L<=R){
    		long long mid=(L+R)>>1;
    		if(check(l,r,mid,v))ans=mid,L=mid+1;
    		else R=mid-1;
    	}
    	Fwrite(ans);
    	*O++='
    ';
    }
    signed main(){
       	freopen("in.txt","r",stdin);
       	freopen("My.out","w",stdout);
    	n=read();m=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	B=(n-1)/SN+1;//2450
    	for(int i=1;i<=n;++i){
    		id[i]=((i-1)/B)+1;
    		bk[id[i]].push_back(mk(a[i],i));
    	}
    	for(int i=1;i<=(n/B)+1;++i){stable_sort(bk[i].begin(),bk[i].end(),cmp);}
    	for(int i=1;i<=m;++i){
    		int opt=read(),l=read(),r=read(),k=read();
    		if(opt==2)change(l,r,k);
    		else query(l,r,k);
    	}
    	fwrite(obuf,O-obuf,1,stdout);
    	return 0;
    }
    
  • 相关阅读:
    【博弈论】【SG函数】【找规律】Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) E. Game of Stones
    【概率dp】Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) D. Jon and Orbs
    【基数排序】Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) C. Jon Snow and his Favourite Number
    【找规律】Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) B. Code For 1
    【kmp算法】poj2185 Milking Grid
    【kmp算法】poj2406 Power Strings
    【DFS】Codeforces Round #398 (Div. 2) C. Garland
    【枚举】【贪心】 Codeforces Round #398 (Div. 2) B. The Queue
    【暴力】Codeforces Round #398 (Div. 2) A. Snacktower
    【kmp算法】uva11475 Extend to Palindrome
  • 原文地址:https://www.cnblogs.com/h-lka/p/15362744.html
Copyright © 2011-2022 走看看