1. 程式人生 > 其它 >2022春每日一題:Day 36

2022春每日一題:Day 36

題目:[JLOI2013]刪除物品

直接做顯然比較複雜,這個題是說對頂棧,但是可以把兩個棧拼在一起,記錄一下棧頂的下標,然後這樣這題就可以轉化為線性上的操作查詢了,用樹狀陣列簡單維護一下就ok了(某個數是否存在,單點修改+區間查詢)
程式碼:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define lowbit(x) x&-x
const int N=1e5+5;
using namespace std;
int n1,n2,a[N],b[N],c[N],n,dy[N];
struct pos
{
	int id,v;
	pos(int ii,int vv)
	{
		id=ii;v=vv;
	}
	pos(){
	}
	friend bool operator < (pos a,pos b)
	{
		return a.v<b.v;
	}
}nums[N];
namespace fenwick
{
	struct fw
	{
		int c;
	}e[N];
	void modify(int x,int v)
	{
		for(int i=x;i<=n;i+=lowbit(i))
		    e[i].c+=v;
	}
	int query(int x)
	{
		int ret=0;
		for(int i=x;i;i-=lowbit(i))
		    ret+=e[i].c;
		return ret;
	}
}
using namespace fenwick;
int main()
{
	scanf("%d %d",&n1,&n2);
	for(int i=1;i<=n1;i++)
	    scanf("%d",&a[i]),c[n1-i+1]=a[i];
	for(int i=1;i<=n2;i++)
	    scanf("%d",&b[i]),c[n1+i]=b[i];
	n=n1+n2;
	for(int i=1;i<=n;i++)
	    nums[i]=pos(i,c[i]);
	sort(nums+1,nums+1+n);
	int last=-1,cnt=1;
	for(int i=1;i<=n;i++)
	{
		if(last!=nums[i].v)
		    last=nums[i].v,cnt=i;
		dy[cnt]=nums[i].id;
	}
	for(int i=1;i<=n;i++)
	    modify(dy[i],1);
	int now=n1;
	long long ret=0;
	for(int i=n;i;i--)
	{
		if(dy[i]<=now)
		{
			ret+=query(now)-query(dy[i]);
			now=dy[i];
		}
		else
		{
			ret+=query(dy[i]-1)-query(now);
			now=dy[i]-1;
		}
		modify(dy[i],-1);
	}
	printf("%lld\n",ret);
	return 0;
}