• luogu P4097 [HEOI2013]Segment


    李超线段树模板题。

    大概思路呢,就是每个区间留着一个标记(tag)表示在这个区间中点函数值最大线段的编号,然后在不停的放线段进去递归处理就行了。

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    const int N=100009,M=40000;
    int n,Q;
    struct LC_Tree
    {
    	int Max[M*4],cnt;
    	double K[N],B[N];
    	
    	double val(int id,int x)
    	{
    		return x*K[id]+B[id];
    	}
    	void Ins(int x,int y,int X,int Y)
    	{
    		cnt++;
    		K[cnt]=1.*(Y-y)/(X-x);
    		B[cnt]=Y-K[cnt]*X;
    	}
    	void Modify(int k,int l,int r,int id)
    	{
    		if(l==r)
    		{
    			Max[k]=val(Max[k],l)>val(id,l)?Max[k]:id;
    			return;
    		}
    		int mid=l+r>>1;
    		if(K[id]>K[Max[k]])
    		{
    			if(val(id,mid)>val(Max[k],mid))
    				Modify(k<<1,l,mid,Max[k]),Max[k]=id;
    			else
    				Modify(k<<1|1,mid+1,r,id);
    		}
    		else
    		{
    			if(val(id,mid)>val(Max[k],mid))
    				Modify(k<<1|1,mid+1,r,Max[k]),Max[k]=id;
    			else
    				Modify(k<<1,l,mid,id);
    		}
    	}
    	void change(int k,int l,int r,int x,int y,int id)
    	{
    		if(l>=x&&r<=y)
    		{
    			Modify(k,l,r,id);
    			return;
    		}
    		int mid=l+r>>1;
    		if(mid>=x)
    			change(k<<1,l,mid,x,y,id);
    		if(mid<y)
    			change(k<<1|1,mid+1,r,x,y,id);
    	}
    	double Query(int k,int l,int r,int x)
    	{
    		if(l==r)
    			return Max[k];
    		int mid=l+r>>1,qwq;
    		double ans=Max[k];
    		if(mid>=x)
    			ans=val(qwq=Query(k<<1,l,mid,x),x)>val(ans,x)?qwq:ans;
    		else
    			ans=val(qwq=Query(k<<1|1,mid+1,r,x),x)>val(ans,x)?qwq:ans;
    		return ans;
    	}
    }A;
    
    void init()
    {
    	scanf("%d",&n);
    }
    
    void work()
    {
    	int last=0,opt,x,y,X,Y;
    	for (int _=1;_<=n;_++)
    	{
    		scanf("%d",&opt);
    		if(opt==0)
    		{
    			scanf("%d",&x);
    			x=(x+last-1)%39989+1;
    			printf("%d
    ",last=A.Query(1,1,M,x));
    		}
    		else
    		{
    			scanf("%d %d %d %d",&x,&y,&X,&Y);
    			x=(x+last-1)%39989+1,y=(y+last-1)%1000000000+1;
    			X=(X+last-1)%39989+1,Y=(Y+last-1)%1000000000+1;
    			if(x>X)
    				swap(x,X),swap(y,Y);
    			A.Ins(x,y,X,Y);
    			A.change(1,1,M,x,X,A.cnt);
    		}
    	}
    }
    
    int main()
    {
    	init();
    	work();
    	return 0;
    }
    
    由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
  • 相关阅读:
    Win32应用中创建多窗口
    同时控制多个UIScrollView对象
    在后台代码中设定控件的Visibility
    VC中使用GDI+
    悬垂指针(Dangling pointer)和野指针(Wild pointer)
    在Windows下通过命令行界面编译并生成 .exe
    C++流重定向到文件
    读写文本文件和二进制文件——二进制模式
    使用MahApps.Metro
    WPF之GUI编写
  • 原文地址:https://www.cnblogs.com/With-penguin/p/12757400.html
Copyright © 2020-2023  润新知