zoukankan      html  css  js  c++  java
  • [HNOI/AHOI2018]转盘

    题目

    洛谷

    做法

    本文部分搬运
    可以发现,如果我需要在转盘上走两圈,不如在第一个物品上停留一段时间,然后再走一圈。

    假设我们固定起点,那么一定是走一圈+多出来的一点点。

    会发现那多出来的一点点假设走到(x),那么以(x+1)为起点就可以只走一圈。

    所以得到结论:最优方案一定是在第一个物品上停留一段时间后走一圈。

    [ans=min_{1leq i leq n}(max_{0 leq j leq n-1}(t_{i+j}-j)+n-1) ]

    [ans=min_{1leq i leq n}(max_{i leq j leq i+n-1}(t_{j}-j+i)+n-1) ]

    [ans=min_{1leq i leq n}(max_{i leq j leq i+n-1}(t_{j}-j)+i+n-1) ]

    (x_i=t_i-i)

    [ans=min_{1leq i leq n}(max_{i leq j leq i+n-1}x_j+i+n-1) ]

    (x_i=t_i-i,x_{i+n}=t_i-i-n,x_i-n=x_{i+n},x_i>x_{i+n})

    [ans=min_{1leq i leq n}(max_{i leq j}x_j+i)+n-1 ]

    考虑后缀,最大值是单调的,也就是一个个区间,每个区间显然最小的(i)最优

    跟二分一样,找到每个区间的最大(i+1)就是下一个区间的最小(i),用线段树维护

    My complete code

    #include<bits/stdc++.h>
    using namespace std;
    typedef int LL;
    const LL maxn=1e6,inf=0x3f3f3f3f;
    LL n,m,p,root,nod;
    LL w[maxn],mx[maxn],son[maxn][2],T[maxn];
    inline LL Query(LL now,LL l,LL r,LL val){
    	if(l==r) return mx[now]<=val?inf:l+1+val;
    	LL mid(l+r>>1);
    	if(mx[son[now][1]]<=val) return Query(son[now][0],l,mid,val);
    	else return min(w[now],Query(son[now][1],mid+1,r,val));
    }
    inline void Update(LL now,LL l,LL r){
    	LL lc(son[now][0]),rc(son[now][1]),mid(l+r>>1);
    	mx[now]=max(mx[lc],mx[rc]);
    	w[now]=Query(lc,l,mid,mx[rc]);
    }
    void Build(LL &now,LL l,LL r){
    	now=++nod;
    	if(l==r){
    		mx[now]=T[l]-l;
    		return;
    	}LL mid(l+r>>1);
    	Build(son[now][0],l,mid), Build(son[now][1],mid+1,r);
    	Update(now,l,r);
    }
    void Modify(LL now,LL l,LL r,LL x,LL y){
    	if(l==r){
    		mx[now]=y-l;
    		return;
    	}LL mid(l+r>>1);
    	if(x<=mid)
    	    Modify(son[now][0],l,mid,x,y);
    	else 
    	    Modify(son[now][1],mid+1,r,x,y);
    	Update(now,l,r);
    }
    int main(){
    	cin>>n>>m>>p;
    	for(LL i=1;i<=n;++i) cin>>T[i];
    	for(LL i=1;i<=n;++i) T[i+n]=T[i];
    	Build(root,1,(n<<1));
    	LL lst;
    	cout<<(lst=min(1+mx[root],w[root])+n-1)<<endl;
    	while(m--){
    		LL x,y; cin>>x>>y;
    		if(p) x^=lst,y^=lst;
    		Modify(root,1,(n<<1),x,y), Modify(root,1,(n<<1),x+n,y);
    	    cout<<(lst=min(1+mx[root],w[root])+n-1)<<endl;
    	}return 0;
    }
    
  • 相关阅读:
    python基础——协程
    Python基础并发编程——进程
    Python基础并发编程——操作系统
    python基础——socket
    Python基础——网络编程
    文件操作
    深浅拷贝和流程控制
    数据类型
    基础知识
    session和cookie
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10433657.html
Copyright © 2011-2022 走看看