zoukankan      html  css  js  c++  java
  • hdu 4747

    题意

    题意:求所有区间的mex和。mex值为没有在该区间出现过的最小非负整数。


    • 先求出1为起点的区间的mex值(递增),用它构造一棵线段树

    • 后:
      用线段树维护当前固定左端点的区间的解的和和最大值,然后更新下一个左端点a[i+1]的区间,那么a[i]就要删除,发现以a[i+1]为左端点的区间所有mex值要把之前第一个mex大于a[i]的位置到下一个a[i]的位置所有值设置为a[i]。
      举个例子: 3 2 1 0 2 3 1
      左端点是a[1] = 3 , mex: 0 0 0 4 4 4 4
      左端点是a[2] = 2 , mex: 0 0 0 3 3 4 4

      可以发现当左端点是a[2] = 2时,[2,3]的mex都是0< a[1] = 3,然后mex[4] = 4 > a[1] = 3的位置4到 a[6] = a[1] = 3的位置6的解都是a[1],所以这里直接区间更新。
      (摘自:https://blog.csdn.net/hyczms/article/details/48143365

    • 因为pushdown忘记下传区间max导致调题2小时


    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <map>
    #define int long long
    using namespace std;
    const int maxn=200003;
    int n,f[maxn],keep[maxn],ans,to[maxn];
    int max(int a,int b){return a>b?a:b;}
    map<int,int>vis,mm;
    struct node{int l,r,sum,flag,mx;}a[maxn<<2];
    void pushup(int x){a[x].sum=a[x<<1].sum+a[x<<1|1].sum,a[x].mx=max(a[x<<1].mx,a[x<<1|1].mx);}
    void pushdown(int x)
    {
    	if(a[x].flag==-1) return;
    	a[x<<1].flag=a[x].flag,a[x<<1].sum=a[x].flag*(a[x<<1].r-a[x<<1].l+1),a[x<<1].mx=a[x].flag;
    	a[x<<1|1].flag=a[x].flag,a[x<<1|1].sum=a[x].flag*(a[x<<1|1].r-a[x<<1|1].l+1),a[x<<1|1].mx=a[x].flag;
    	a[x].flag=-1;
    }
    void build(int x,int left,int right)
    {
    	a[x].l=left,a[x].r=right,a[x].flag=-1;
    	if(left==right) return a[x].mx=a[x].sum=keep[left],void();
    	int mid=left+right>>1;
    	build(x<<1,left,mid),build(x<<1|1,mid+1,right);
    	pushup(x);
    }
    void modify(int x,int left,int right,int d)
    {
    	if(a[x].r<left||a[x].l>right) return;
    	if(left<=a[x].l&&right>=a[x].r) return a[x].sum=d*(a[x].r-a[x].l+1),a[x].mx=a[x].flag=d,void();
    	pushdown(x);
    	modify(x<<1,left,right,d),modify(x<<1|1,left,right,d);
    	pushup(x);
    }
    int query(int x,int val)//查找第一个大于等于 val的数的位置 
    {
    	if(a[x].mx<val) return -1;
    	if(a[x].l==a[x].r) return a[x].l;
    	pushdown(x);
    	return val<=a[x<<1].mx?query(x<<1,val):query(x<<1|1,val);
    }
    void getfirst()
    {
    	vis.clear();
    	for(int i=1,cnt=0;i<=n;++i)
    	{
    		vis[f[i]]=1;
    		while(vis[cnt]) ++cnt;
    		keep[i]=cnt;
    	}
    }
    signed main()
    {
    //	freopen("tmp.in","r",stdin);
    	while(scanf("%lld",&n)&&n)
    	{
    		mm.clear();
    		memset(to,0,sizeof(to));
    		for(int i=1;i<=n;++i) 
    		{
    			scanf("%lld",&f[i]);
    			if(mm[f[i]]) to[mm[f[i]]]=i;//to[a]表示下一个a的出现位置
    			mm[f[i]]=i;
    		}
    		getfirst(),build(1,1,n),ans=a[1].sum;
    		for(int i=2;i<=n;++i)
    		{
    			modify(1,i-1,i-1,0);
    			int tmpl=query(1,f[i-1]+1),tmpr=!to[i-1]?n:to[i-1]-1;
    			if(tmpl!=-1) modify(1,tmpl,tmpr,f[i-1]);
    			ans+=a[1].sum;
    			if(!a[1].sum) break;
    		}
    		cout<<ans<<'
    ';
    	}
    	return 0;
    }
    
  • 相关阅读:
    Altova MapForce AMS/ACI/ISF自定义模板
    CSS currentColor 变量
    CSS之咖啡菜单网页设计
    css3之3D 旋转立方体与哆啦A梦
    CSS3 3D转换——rotateX(),rotateY(),rotateZ()
    Emmet常用语法
    CSS3 的动画属性
    CSS的五种基本选择器
    盒模型之标准模型与怪异模型
    CSS3的2D 转换——旋转,缩放,translate(),skew(),matrix()
  • 原文地址:https://www.cnblogs.com/wuwendongxi/p/14540376.html
Copyright © 2011-2022 走看看