zoukankan      html  css  js  c++  java
  • 动态维护凸包的另一种方法

    题意,二维加入一个点,删除一个点,动态维护左上凸壳大小。
    朴素做法,时间线段树加动态凸包。
    神仙做法
    考虑对横轴建立线段树,每个节点保存左上凸壳大小以及最大值,合并左右区间时,再右区间中找到第一个比左边最大值大的位置,然后递归查右区间中左端点到该位置的凸壳大小。
    时间复杂度(O(nlog^2(n)))

    #pragma GCC optimize(3)
    #include <bits/stdc++.h>
    using namespace std;
    const double eps=1e-11;
    const int N=1e5+10;
    struct node{
    	int len;
    	double mx;
    }T[N<<3];
    int fcmp(double x,double y){
    	if (fabs(x-y)<eps) return 0;
    	return (x>y?1:-1);
    }
    int fir(int ind,int l,int r,double mx){
    //	cerr<<"fir"<<ind<<" "<<l<<" "<<r<<" "<<mx<<endl;
    	if (l==r) return (fcmp(T[ind].mx,mx)>0?l:-1);
    	int mid=(l+r)>>1;
    	return ((fcmp(T[ind<<1].mx,mx)>0)?fir(ind<<1,l,mid,mx):fir(ind<<1|1,mid+1,r,mx));
    }
    int ask(int ind,int l,int r,int rr){
    	//cerr<<"ask"<<ind<<" "<<l<<" "<<r<<" "<<rr<<endl;
    	//Sleep(1000);
    	if (l>rr) return 0;
    	if (r<=rr) return T[ind].len;
    	int mid=(l+r)>>1;
    	if (rr<=mid) return ask(ind<<1,l,mid,rr);
    	
    	int pos=fir(ind<<1|1,mid+1,r,T[ind<<1].mx);
    	if (pos==-1) return T[ind<<1].len;
    	else return T[ind<<1].len+ask(ind<<1|1,mid+1,r,rr)-ask(ind<<1|1,mid+1,r,pos-1);
    }
    void build(int ind,int l,int r){
    	T[ind].len=0;
    	T[ind].mx=0;
    	if (l==r){
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(ind<<1,l,mid);
    	build(ind<<1|1,mid+1,r);
    }
    void modify(int ind,int l,int r,int p,double val){
    	//cerr<<"modify"<<ind<<" "<<l<<" "<<r<<" "<<p<<" "<<val<<endl;
    	if (l==r){
    		T[ind].len=1;
    		T[ind].mx=val;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if (p<=mid) modify(ind<<1,l,mid,p,val);
    	else modify(ind<<1|1,mid+1,r,p,val);
    	
    	T[ind].mx=max(T[ind<<1].mx,T[ind<<1|1].mx);
    	int pos=fir(ind<<1|1,mid+1,r,T[ind<<1].mx);
    	//cerr<<"pos"<<pos<<endl;
    	if (pos==-1) T[ind].len=T[ind<<1].len;
    	else T[ind].len=T[ind<<1].len+T[ind<<1|1].len-ask(ind<<1|1,mid+1,r,pos-1);
    	//cerr<<"len"<<ind<<" "<<T[ind].len<<endl;
    }
    int n,m;
    int main(){
    	//freopen("1012.in","r",stdin);
    	//freopen("1012.out","w",stdout); 
    	int ca;
    	scanf("%d",&ca);
    	while (ca--){
    		scanf("%d%d",&n,&m);
    		build(1,1,n);
    		for (int i=1; i<=m; ++i){
    			//cerr<<"I"<<i<<endl;
    			int id;
    			double height;
    			scanf("%d%lf",&id,&height);
    			height/=id;
    			//cerr<<"height"<<height<<endl;
    			modify(1,1,n,id,height);
    			cout<<T[1].len<<'
    ';
    		}
    	}
    }
    /*
    2
    3 4
    2 4
    3 6
    1 1000000000
    1 1
    
    3 4
    2 4
    3 6
    1 1000000000
    1 1
    */
    
  • 相关阅读:
    排序算法的体验游戏
    【转】[Java] HashMap使用的示例
    【转】【Android】使用BaseAdapter实现复杂的ListView
    【转】Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例
    【转】Java集合框架List,Map,Set等全面介绍
    【转】java参数传递(超经典)
    bluetooth记录
    【转】Java 字符串常用操作(String类)
    【转】Java中字符串中子串的查找共有四种方法(indexof())
    【转】BLE 学习记录
  • 原文地址:https://www.cnblogs.com/Yuhuger/p/13894373.html
Copyright © 2011-2022 走看看