玲珑OJ1088【蜜汁尺取】

前言(膜法):

早上10点多开始膜的,然后到中午交了一发,感觉膜法不对啊!然后就兴起小窗了一发管理员,然后管理员给我发了in,out数据。。。可是太大并没有什么可取性。。。
还是自己试,然后发现自己搞的案例都过,后面放着不玩了,然后队友给了我一题以前做过的dfs写,然后写了以后T了,后面我就跟他讲这道题。。。讲完好我说我的方法,他硬是不懂我的尺取,然后搞了一个破案例我模拟发现,卧槽我左指针移的时候发现,区间突然没有取前m最大惹,后面在左指针移的时候改了一下,gg,wa的。然后继续测,继续wa。然后发现噢噢噢噢,那样子搞的!始终都要前m大,然后就这样了,膜了一发过了。。。破水题,坑了一天,不过事后发现以后做题要对重要条件特别照顾,始终照顾。然后CF也没打。。。万事大吉,然后就和女朋友去散步了。

题意:
先选一段连续的区间,能够免费m个,免费是任意位置,求一个获得价值最大;

思路:

重点就是在于怎么搞出一个区间的前m大,而且是始终都要。

尺取,对区间里的数进行分类,一类是免费,一类是付钱,那我肯定是免费最贵的,因为最终我的钱多呀!

然后具体操作是两个优先队列搞的,一个队列是付钱的最大,一个队列是免费的最小,这样维护复杂度还好吧。

//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;

const int N=1e5+10;
struct asd{
    int id,w;
    friend bool operator< (asd n1,asd n2)
	{
        if(n1.w==n2.w) return n1.id>n2.id;
        return n1.w>n2.w;
    }
};

struct dsa{
    int id,w;
	friend bool operator< (dsa n1,dsa n2)
	{
        if(n1.w==n2.w) return n1.id>n2.id;
        return n1.w<n2.w;
	}
};

int a[N],b[N],sum[N];
bool vis[N];
priority_queue<asd>q;	//区间内免费的物品 
priority_queue<dsa>p;	//区间内花费的物品 
int cost,val,out;
dsa have(int s)
{
	dsa now;
	while(!p.empty())
	{
		if(p.top().id<s)
			p.pop();
		else
			break;
	}
	if(!p.empty())
	{
		now=p.top();
		return now;
	}
	now.id=0;
	return now;
}

asd get_q(int s)
{
	while(!q.empty())
		if(q.top().id<s)
		{
			q.pop();	
			out--;
		}
		else
			break;
	asd now;
	now=q.top();
	return now;
}

int main()
{
    int T,n,m,k;
    scanf("%d",&T);
    while(T--)
    {
        while(!q.empty())
			q.pop();
		while(!p.empty())
			p.pop();
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        sum[0]=0;
        for(int i=1;i<=n;i++)
		{
            scanf("%d",&b[i]);
            sum[i]=sum[i-1]+b[i];
            vis[i]=false;
        }
        asd now,nex;
        dsa nnn,mmm;
        int s,t;
        out=0;	//out代表,在队列里的实际已经出队的元素个数 
        cost=0;	//代表花费。 
        val=0;	//代表得的价值。
		s=t=1;
		while(s<=n)
		{
			while(t<=n)
			{
				if((q.size()-out)<m)
				{
					nnn.id=t;nnn.w=a[t];p.push(nnn);
					cost+=nnn.w;
					mmm=have(s);
					cost-=mmm.w;
					now.id=mmm.id;now.w=mmm.w;
					vis[now.id]=1;
					p.pop();
					q.push(now);
					val=max(val,sum[t]-sum[s-1]);
					t++;
				}
				else if((q.size()-out)==m)
				{
					now=get_q(s);
					if(cost+a[t]>k&&cost+now.w>k)
						break; 
					
					nnn.id=t;nnn.w=a[t];p.push(nnn);
					cost+=a[t];
					mmm=have(s);
					if(mmm.w>now.w)
					{
						cost-=mmm.w;
						cost+=now.w;
						q.pop();
						p.pop();
						nnn.id=now.id;nnn.w=now.w;
						vis[nnn.id]=0;
						p.push(nnn);
						nex.id=mmm.id;nex.w=mmm.w;
						vis[nex.id]=1;
						q.push(nex);
					}
					val=max(val,sum[t]-sum[s-1]);
					t++;		
				}
				else break;
			}
			//printf("%d %d
",s,t);
			//printf("%d
",val);
			if(vis[s])
			{
				vis[s]=false;
				out++;
			}
			else
				cost-=a[s];
			s++;
		}
        printf("%d
",val);
    }
    return 0;
}
/*
100 
6 1 4
5 3 2 4 1 6
2 4 3 1 6 5
5 1 6
1 2 5 4 3
2 2 5 4 8
5 2 6
1 2 5 4 3
2 2 5 4 8
6 2 4
5 3 2 4 1 6
2 4 3 1 6 5
6 2 4
1 7 1 7 1 6
2 4 3 1 6 3 
6 2 4
1 7 1 7 1 6
2 4 3 1 6 3 
5 2 2
1 2 5 4 3
2 2 5 4 8
5 1 1
8 5 4 3 2
1 2 3 4 5
4 1 3
4 2 2 3
3 2 4 5

*/



原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777425.html