• #整体二分 or 主席树#洛谷 7424 [THUPC2017] 天天爱射击


    题目

    给定(n)条线段(x_i,y_i,k_i)(m)个点(点有顺序),
    对于每个点,问有多少条线段是第(k_i)次被该点经过。


    分析(主席树)

    将点按坐标排序建主席树那么就是一道静态第(k)小问题


    代码(主席树)

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define rr register
    using namespace std;
    const int N=200011;
    struct rec{int l,r,kth;}q[N];
    int a[N],rk[N],ans[N],cnt,n,m,ls[N<<5],rs[N<<5],w[N<<5],rt[N];
    inline signed iut(){
    	rr int ans=0,f=1; rr char c=getchar();
    	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans*f;
    }
    inline void print(int ans){
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48); 
    }
    bool cmp(int x,int y){return a[x]<a[y];}
    inline void update(int &rt,int l,int r,int x){
    	rr int trt=++cnt,mid=(l+r)>>1;
    	w[trt]=w[rt]+1,ls[trt]=ls[rt],rs[trt]=rs[rt],rt=trt;
    	if (l==r) return;
    	if (x<=mid) update(ls[rt],l,mid,x);
    	    else update(rs[rt],mid+1,r,x);
    }
    inline signed query(int lt,int rt,int l,int r,int kth){
    	if (l==r) return l;
    	rr int mid=(l+r)>>1;
    	if (kth<=w[ls[rt]]-w[ls[lt]]) return query(ls[lt],ls[rt],l,mid,kth);
    	    else return query(rs[lt],rs[rt],mid+1,r,kth-w[ls[rt]]+w[ls[lt]]);
    }
    signed main(){
    	n=iut(),m=iut();
    	for (rr int i=1;i<=n;++i) q[i]=(rec){iut(),iut(),iut()};
    	for (rr int i=1;i<=m;++i) a[i]=iut(),rk[i]=i;
    	sort(rk+1,rk+1+m,cmp);
    	for (rr int i=1,j=1;i<N;++i){
    		rt[i]=rt[i-1];
    		for (;j<=m&&a[rk[j]]<=i;++j)
    		    update(rt[i],1,n,rk[j]);
    	}
    	for (rr int i=1;i<=n;++i){
    		if (q[i].kth>w[rt[q[i].r]]-w[rt[q[i].l-1]]) continue;
    		++ans[query(rt[q[i].l-1],rt[q[i].r],1,n,q[i].kth)];
    	}
    	for (rr int i=1;i<=m;++i) print(ans[i]),putchar(10);
    	return 0;
    } 
    

    分析(整体二分)

    同样,可以二分在第几个点时线段恰好被经过(k_i)次,整体二分即可,

    虽然整体二分两个log,但是比主席树一个log常数小


    代码(整体二分)

    #include <cstdio>
    #include <cctype>
    #define rr register
    using namespace std;
    const int N=200011;
    struct rec{int l,r,x;}q[N],q1[N],q2[N];
    int ans[N],a[N],c[N],n,m;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline void print(int ans){
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48); 
    }
    inline void update(int x,int y){
    	for (;x<N;x+=-x&x) c[x]+=y;
    }
    inline signed query(int x){
    	rr int ans=0;
    	for (;x;x-=-x&x) ans+=c[x];
    	return ans;
    }
    inline void dfs(int L,int R,int l,int r){
    	if (l>r) return;
    	if (L==R){
    		ans[L]=r-l+1;
    		return;
    	}
    	rr int mid=(L+R)>>1,tot1=0,tot2=0;
    	for (rr int i=L;i<=mid;++i) update(a[i],1);
    	for (rr int i=l;i<=r;++i){
    		rr int now=query(q[i].r)-query(q[i].l-1);
    		if (q[i].x<=now) q1[++tot1]=q[i];
    		    else q[i].x-=now,q2[++tot2]=q[i];
    	}
    	for (rr int i=L;i<=mid;++i) update(a[i],-1);
    	for (rr int i=1;i<=tot1;++i) q[l+i-1]=q1[i];
    	for (rr int i=1;i<=tot2;++i) q[l+i+tot1-1]=q2[i];
    	dfs(L,mid,l,l+tot1-1),dfs(mid+1,R,l+tot1,r);
    }
    signed main(){
    	n=iut(),m=iut();
    	for (rr int i=1;i<=n;++i)
    		q[i]=(rec){iut(),iut(),iut()};
    	for (rr int i=1;i<=m;++i) a[i]=iut();
    	dfs(1,m+1,1,n);
    	for (rr int i=1;i<=m;++i) print(ans[i]),putchar(10);
    	return 0;
    } 
    
  • 相关阅读:
    3.3测试复盘
    计算机网络-运输层面试题整理
    3.2专项测试复盘
    2.27专项测试复盘
    2.26排序专项测试复盘
    2.25专项测试复盘
    前端基础笔记1
    2.24专项测试复盘
    2.23专项测试复盘
    更新pip报错AttributeError: 'NoneType' object has no attribute 'bytes'
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14609185.html
Copyright © 2020-2023  润新知