zoukankan      html  css  js  c++  java
  • 7.3总结

    7.3总结

    得分情况

    估分:60+40+100=200

    实际:60+40+30=130

    Rank 9

    萎的一批

    好歹把T1T2的暴力分拿满了

    T1

    比赛的时候想了很久没有思路,就打暴力把人一个个塞进去,拿了暴力分60分

    正解:

    操作一:

    首先,放人进去的时候,优先级是固定的。所以我们可以用后序遍历把优先级搞出来,用一个堆来维护哪些位置是空的,每次放人的时候就从堆里面找一个位置,删人的时候放一个位置进堆里面。(用线段树也可以搞,我就是用线段树打的)

    操作二:

    我们已经知道哪些点有人,那么把一个人删去时,就用倍增找到他最上面一个有人的节点,把它删去就好了。(用树链剖分也可以搞,cgh打了树剖)

    T2

    比赛的时候想了很久也没什么思路,就把40分暴力分给拿到了。

    正解

    首先考虑一种暴力:设f[i][0/1]表示前面的数与i进行位运算,结果的最大值和方案数。这样子做插入是O((2^{16}))的,询问是O(1)的。

    怎么平衡一下插入和询问的时间复杂度呢?

    运用广义平衡规划的思想,类似折半搜索一样,设f[i][j][0/1]表示前面的数中,前八位为i,与某个后八位为j的数进行位运算,后八位结果的最大值和方案数。

    这样一来,插入时i是固定的,我们只用枚举j来更新f;而询问时j是固定的,只用枚举i来更新ans。

    ~好巧妙的思想啊~

    T3

    谴责出题人,暴力随便水过。

    我以为它是满足二分性的,结果又TLE有WA爆炸了。

    早知道就打暴力算了。

    正解

    首先,把读入的串分段,同一段里面满足每个数%d都是同一个值

    由于不能有重复的数,所以要求一个maright[l]来表示最大右端点使a[l~maright[l]]中没有相同的数。

    用哈希或map随便搞搞就好了

    然后(n^2)暴力就切了哈哈

    那么为了避免负数等情况,我们处理一下数据。对于一段每个数a[x],令a[x]=(a[x]-min)/d+1,min即为这一段的最小值。

    当l,r为左右端点时,满足(max{a_{l...r}}-min{a_{l...r}}+1leq r-l+1+k)即可更新答案。

    考虑枚举左端点,找最大的右端点

    设ma[r]表示当左端点为l时的(max{a_{l...r}}),mi[r]表示当左端点为l时的(min{a_{l...r}})

    化一下式子变成(ma[r]-mi[r]-rleq k-l),右边只与l有关。

    (b[r]=ma[r]-mi[r]-r),用线段树维护b,那么只用找出最大的r使(b[r]leq k-l)且r<=maright[l]

    倒着枚举l,这样每一个ma[r]和mi[r]就只会单调上升或下降。其实ma与mi两个数组本身也是从左到右单调的。

    那么当我们把l-1时,从l往后某一段ma就会由 一个小于a[l-1]的数 变为a[l-1]。但是我们不能直接用区间赋值,因为那样的话,由于那一段区间的ma[r]和mi[r]可能不同,所以没法更新区间b[r]的最小值。但是用区间加法就可以了。所以要打两个单调栈维护相同的一块块ma[r]和mi[r]。如果这个区间的ma[r]都相同(其实就等于a[r])且小于a[l],更新标记的时候给这个区间加上a[l]-ma[r];如果这个区间的mi[r](其实就等于a[r])都相同且大于a[l],更新标记的时候给这个区间加上mi[r]-a[l]。//这个地方打反了正负号调了一个小时。

    由于线段树里面我们维护的是b[r]的最小值,所以最后用线段树的区间查询找l~n里面最靠右的满足b[r](leq)k-l并且r<=maright[l]的点就是以l为左端点的答案。

    (这几天做过的最难的题目)

    (其实也没多难,暴力就切了嘛233)

    //for the moon
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define mod 19260817
    using namespace std;
    
    struct qy
    {
    	int mi,add;
    };
    
    int n,k,d,i,j,st,en,t;
    int a[200005],maright[200005];
    int ans1,ans2;
    int hash[mod+5];
    int ma[200005],mi[200005];
    int z1[200005],z2[200005];
    qy tree[800005];
    
    void pushdown(int k,int l,int r)
    {
    	if (l!=r)
    	{
    		tree[k*2].add+=tree[k].add;
    		tree[k*2+1].add+=tree[k].add;
    		tree[k*2].mi+=tree[k].add;
    		tree[k*2+1].mi+=tree[k].add;
    	}
    	tree[k].add=0;
    }
    
    void update(int k,int l,int r)
    {
    	tree[k].mi=2100000000;
    	int mid=(l+r)/2;
    	if (l<=mid) tree[k].mi=min(tree[k].mi,tree[k*2].mi);
    	if (mid+1<=r)
    	tree[k].mi=min(tree[k].mi,tree[k*2+1].mi);
    }
    
    void insert(int k,int l,int r,int x)
    {
    	pushdown(k,l,r);
    	if (l==r)
    	{
    		tree[k].add=0;
    		tree[k].mi+=-x;
    	}
    	else
    	{
    		int mid=(l+r)/2;
    		if (x<=mid) insert(k*2,l,mid,x);
    		else insert(k*2+1,mid+1,r,x);
    		update(k,l,r);
    	}
    }
    
    void add(int k,int l,int r,int x,int y,int z)
    {
    	pushdown(k,l,r);
    	if ((l<=y)&&(r>=x))
    	{
    		if ((l>=x)&&(r<=y))
    		{
    			tree[k].add+=z;
    			tree[k].mi+=z;
    			return;
    		}
    		int mid=(l+r)/2;
    		add(k*2,l,mid,x,y,z);
    		add(k*2+1,mid+1,r,x,y,z);
    		update(k,l,r);
    	}
    }
    
    int query(int k,int l,int r,int x,int y,int z)
    {
    	pushdown(k,l,r);
    	if ((l<=y)&&(r>=x))
    	{
    		int mid=(l+r)/2;
    		if ((l>=x)&&(r<=y))
    		{
    			if (l==r) return l;
    			else
    			{
    				if (tree[k*2+1].mi<=z) return query(k*2+1,mid+1,r,x,y,z);
    				else return query(k*2,l,mid,x,y,z);
    			}
    		}
    		
    		int tt=0;
    		if (tree[k*2+1].mi<=z)
    		tt=query(k*2+1,mid+1,r,x,y,z);
    		if (tt!=0) return tt;
    		else return query(k*2,l,mid,x,y,z);
    	}
    	else
    	return 0;
    }
    
    void clear(int k,int l,int r)
    {
    	tree[k].mi=tree[k].add=0;
    	int mid=(l+r)/2;
    	if (l!=r)
    	{
    		clear(k*2,l,mid);
    		clear(k*2+1,mid+1,r);
    	}
    }
    
    void does(int st,int en)
    {
    	int mii=2000000000;
    	int l,r,ll,rr;
    	for (i=st;i<=en;i++)
    	mii=min(mii,a[i]);
    	for (i=st;i<=en;i++)
    	a[i]=(a[i]-mii)/d+1;
    	
    	z1[0]=z2[0]=0;
    	for (l=en;l>=st;l--)
    	{
    		ma[l]=mi[l]=a[l];
    		insert(1,st,en,l);
    		while ((z1[0]>=1)&&(a[z1[z1[0]]]<=a[l]))
    		{
    			ll=z1[z1[0]];
    			rr=z1[z1[0]-1]-1;
    			if (z1[0]==1) rr=en;
    			add(1,st,en,ll,rr,a[l]-a[ll]);
    			z1[0]--;
    		}
    		z1[++z1[0]]=l;
    		while ((z2[0]>=1)&&(a[z2[z2[0]]]>=a[l]))
    		{
    			ll=z2[z2[0]];
    			rr=z2[z2[0]-1]-1;
    			if (z2[0]==1) rr=en;
    			add(1,st,en,ll,rr,a[ll]-a[l]);
    			z2[0]--;
    		}
    		z2[++z2[0]]=l;
    		r=query(1,st,en,l,maright[l],k-l);
    		if (r-l>=ans2-ans1)
    		{
    			ans1=l;
    			ans2=r;
    		}
    	}
    	clear(1,st,en);
    }
    
    int js(long long x)
    {
    	return (long long)x%mod*x%mod;
    }
    
    int main()
    {
    	freopen("read.in","r",stdin);
    	scanf("%d%d%d",&n,&k,&d);
    	for (i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		a[i]=a[i]+1000000000;
    	}
    	maright[n]=n;
    	hash[js(a[n])]=n;
    	for (i=n-1;i>=1;i--)
    	{
    		t=hash[js(a[i])];
    		maright[i]=maright[i+1];
    		if (t!=0)
    		maright[i]=min(t-1,maright[i]);
    		hash[js(a[i])]=i;
    	}
    	st=1;
    	ans1=ans2=1;
    	for (i=2;i<=n;i++)
    	{
    		if (a[i]%d!=a[i-1]%d)
    		{
    			en=i-1;
    			does(st,en);
    			st=i;
    		}
    	}
    	does(st,n);
    	printf("%d %d",ans1,ans2);
    	return 0;
    }
    
  • 相关阅读:
    Ducking
    MINITAB(二)
    JFreechart
    linux命令0424
    JAVA哈哈镜
    HTML(四)
    The 3n+1 problem
    [转载]:【读书笔记】.NET本质论
    ER图基本步骤
    [从架构到设计]第一回:设计,应该多一点(转载)
  • 原文地址:https://www.cnblogs.com/leason-lyx/p/11148099.html
Copyright © 2011-2022 走看看