zoukankan      html  css  js  c++  java
  • luogu P3527 [POI2011]MET-Meteors

    此题可以使用整体二分解决。

    我们发现把所有国家收集陨石的情况都查一遍的总复杂度是固定的,那么这时候我们就可以放心的使用整体二分:

    • (solve(l,r,x,y))表示([x,y])这些国家,他们的答案范围在([l,r])内,并设(mid)([l,r])的中点

    • 我们先把([l,mid])范围内的陨石落下,再对每个国家查询:若此国家已经收集够陨石,则他们所属答案区间为([l,mid]),否则更新此国家的需要陨石的数目,然后把它放进([mid+1,r])

    分析时间复杂度(重点):我们可以类比线段树的把我们的分支结构看成(O(logn))层,然后我们发现对于国家查询,每层的复杂度相同(因为每层都会把所有国家查一遍),由于使用树状数组,所以每层均摊复杂度(O(nlogn)),一共(O(log))层,所以总复杂度为(O(nlog^2n))

    代码:

    #pragma GCC optimize(2)
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    
    using namespace std;
    
    typedef long long LL;
    const int N=300009;
    int n,m,L[N],R[N],A[N],k,ans[N],f;
    LL c[N];
    struct Edge
    {
    	int nxt,to;
    }b[N*2];
    struct Question
    {
    	LL need;
    	int head,id;
    }q[N],q_[N],Q_[N];
    
    void Add(int from,int to)
    {
    	b[++f].nxt=q[from].head;
    	b[f].to=to;
    	q[from].head=f;
    }
    
    inline void add(int x,LL v)
    {
    	while(x<=m)
    	{
    		c[x]+=v;
    		x+=x&(-x);
    	}
    }
    
    inline LL getsum(int x)
    {
    	LL ans=0;
    	while(x)
    	{
    		ans+=c[x];
    		x-=x&(-x);
    	}
    	return ans;
    }
    
    inline int read()
    {
    	int x=0;
    	char c=getchar();
    	while(c<'0'||c>'9')
    		c=getchar();
    	while(c>='0'&&c<='9')
    		x=x*10+c-'0',c=getchar();
    	return x;
    }
    
    void init()
    {
    	n=read(),m=read();
    	for (int i=1,x;i<=m;i++)
    		x=read(),Add(x,i);
    	for (int i=1;i<=n;i++)
    		q[i].need=read(),q[i].id=i;
    	k=read();
    	for (int i=1;i<=k;i++)
    		L[i]=read(),R[i]=read(),A[i]=read();
    }
    
    inline void Modify(int x,int y,LL v)
    {
    	add(x,v),add(y+1,-v);
    }
    
    inline LL Query(int x)
    {
    	return getsum(x);
    }
    
    inline void solve(int l,int r,int x,int y)
    {
    	if(l==r)
    	{
    		for (int i=x;i<=y;i++)
    			ans[q[i].id]=l;
    		return;
    	}
    	int mid=l+r>>1;
    	for (int i=l;i<=mid;i++)
    		if(L[i]<=R[i])
    			Modify(L[i],R[i],A[i]);
    		else
    			Modify(L[i],m,A[i]),Modify(1,R[i],A[i]);
    	int cnt=0,cnt_=0;
    	for (int i=x;i<=y;i++)
    	{
    		int flag=0,j;
    		for (j=q[i].head;j;j=b[j].nxt)
    		{
    			int v=b[j].to;
    			LL Q=Query(v);
    			if(q[i].need<=Q)
    			{
    				flag=1;
    				break;
    			}
    			q[i].need-=Q;
    		}
    		if(flag)
    		{
    			for (int k=q[i].head;k!=j;k=b[k].nxt)
    				q[i].need+=Query(b[k
    				].to);
    			q_[++cnt]=q[i];
    		}
    		else
    			Q_[++cnt_]=q[i];
    	}
    	for (int i=l;i<=mid;i++)
    		if(L[i]<=R[i])
    			Modify(L[i],R[i],-A[i]);
    		else
    			Modify(L[i],m,-A[i]),Modify(1,R[i],-A[i]);
    	int i=x;
    	for (int j=1;j<=cnt;j++,i++)
    		q[i]=q_[j];
    	for (int j=1;j<=cnt_;i++,j++)
    		q[i]=Q_[j];
    	if(cnt)
    		solve(l,mid,x,x+cnt-1);
    	if(cnt_)
    		solve(mid+1,r,x+cnt,y);
    }
    
    void work()
    {
    	solve(1,k+1,1,n);
    	for (int i=1;i<=n;i++)
    		if(ans[i]==k+1)
    			puts("NIE");
    		else
    			printf("%d
    ",ans[i]);
    }
    
    int main()
    {
    	init();
    	work();
    	return 0;
    }
    
    由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
  • 相关阅读:
    nginx 服务器重启命令,关闭
    eclipse实现热部署和热启动
    Intellij IDEA 文件修改提示星号
    IntelliJ IDEA 自动编译功能无法使用,On 'update' action:选项里面没有update classes and resources这项
    idea最常使用的快捷键
    centos 切换用户显示bash-4.2$,不显示用户名路径的问题
    汉诺塔
    C语言笔记
    @org.springframework.beans.factory.annotation.Autowired(required=true)
    Error creating bean with name 'xxxx' defined in URL
  • 原文地址:https://www.cnblogs.com/With-penguin/p/13138923.html
Copyright © 2011-2022 走看看