zoukankan      html  css  js  c++  java
  • 【BZOJ4979】凌晨三点的宿舍(分治)

    传送门

    给定一个序列,每个位置一个值hih_i
    定义22个位置(i,j),i<j(i,j),i<j的距离为ji+hi+hj2min(h[k],k[i,j])j-i+h_i+h_j-2*min(h[k],kin[i,j])
    求有多少对节点的距离小于等于kk
    n2e5n le2e5


    考虑分治
    对于当前区间l,mid,rl,mid,r
    mnimn_i表示iimidmid的最小值
    求有多少i[l,mid],j[mid+1,r]iin[l,mid],jin[mid+1,r]满足
    ji+hi+hj2min(mni,mnj)kj-i+h_i+h_j-2*min(mn_i,mn_j)le k
    假设此时min=mnimin=mn_i,另一种会在相反的i,ji,j统计到
    hii2mnikjhjh_i-i-2*mn_ile k-j-h_j
    对每个ii插入树状数组后对jj查询就是了
    复杂度O(nlog2n)O(nlog^2n)

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pii pair<int,int>
    #define mk make_pair
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=200005;
    const int Mr=600006;
    const int M=1000005;
    #define lowbit(x) (x&(-x))
    struct Bit{
    	int tr[M];
    	inline void update(int p,int k){
    		p+=Mr;
    		for(;p<M;p+=lowbit(p))tr[p]+=k;
    	}
    	inline int query(int p,int res=0){
    		p=min(p+Mr,M-1);
    		for(;p;p-=lowbit(p))res+=tr[p];
    		return res;
    	}
    }A,B;
    int n,m,k,h[N];
    ll ans;
    vector<pii> q;
    struct room{
    	int x,y,val;
    	room(int _x=0,int _y=0,int _val=0):x(_x),y(_y),val(_val){}
    	friend inline bool operator <(const room &a,const room &b){
    		return a.val<b.val;
    	}
    };
    inline void calc(const vector<pii> &q){
    	for(int i=0,j=0;i<q.size();i++){
    		while(q[j].second+k<q[i].second)j++;
    		ans+=i-j;
    	}
    }
    inline void solve(int l,int r,vector<pii> &vec){
    	if(!vec.size())return;
    	if(l==r)return calc(vec);
    	int mid=((l+r)>>1);
    	vector<pii> ql,qr;
    	for(int i=0;i<vec.size();i++){
    		if(vec[i].first<=mid)ql.push_back(vec[i]);
    		else qr.push_back(vec[i]);
    	}
    	solve(l,mid,ql),solve(mid+1,r,qr);
    	vector<room> now;
    	for(int i=ql.size()-1,p=mid,mn=h[p];~i;p--){
    		mn=min(mn,h[p]);
    		while(~i&&ql[i].first==p){
    			now.push_back(room(p,ql[i].second,min(mn,ql[i].second)));
    			i--;
    		}
    	}
    	for(int i=0,p=mid+1,mn=h[p];i<qr.size();p++){
    		mn=min(mn,h[p]);
    		while(i<qr.size()&&qr[i].first==p){
    			now.push_back(room(p,qr[i].second,min(mn,qr[i].second)));
    			i++;
    		}
    	}
    	sort(now.begin(),now.end());
    	for(int i=0;i<now.size();i++){
    		room &t=now[i];
    		if(t.x<=mid){
    			A.update(t.y-t.x-2*t.val,1);
    			ans+=B.query(k+t.x-t.y);
    		}
    		else{
    			B.update(t.y+t.x-2*t.val,1);
    			ans+=A.query(k-t.x-t.y);
    		}
    	}
    	for(int i=0;i<now.size();i++){
    		room &t=now[i];
    		if(t.x<=mid)A.update(t.y-t.x-2*t.val,-1);
    		else B.update(t.y+t.x-2*t.val,-1);
    	}
    }
    int main(){
    	n=read(),k=read();
    	for(int i=1;i<=n;i++)h[i]=read();
    	m=read();
    	for(int i=1;i<=m;i++){
    		int x=read(),y=read();
    		q.push_back(mk(x,y));
    	}
    	sort(q.begin(),q.end());
    	solve(1,n,q);
    	cout<<ans;
    }
    
  • 相关阅读:
    loj#6433. 「PKUSC2018」最大前缀和(状压dp)
    PKUWC2019游记
    10. Regular Expression Matching
    9. Palindrome Number
    8. String to Integer (atoi)
    7. Reverse Integer
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    4. Median of Two Sorted Arrays
    3. Longest Substring Without Repeating Characters
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145642.html
Copyright © 2011-2022 走看看