zoukankan      html  css  js  c++  java
  • 【BZOJ3333】排队计划 树状数组+线段树

    【BZOJ3333】排队计划

    Description

    Input

    Output

    Sample Input

    6 2
    160 163 164 161 167 160
    2
    3

    Sample Output

    6
    3
    1

    HINT

    题解:本题的思路比较好,可惜我只想到了一半。

    先用树状数组求出f[i],代表i和后面的人能构成多少逆序对。然后我们发现,每次放哨时,只有出列的那些同学的f值会发生变化(变成0),而其他人的f值不发生改变,所以我们将这些出列的同学找出来暴力清零即可。

    但是放哨后高度的排列顺序会变啊,这样会不会对其他询问有影响呢?显然不会啊!f值都清零了还会有什么影响?所以我们可以用线段树维护区间最大值,这样就能找到每个人后面所有比它小的了。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define lson x<<1
    #define rson x<<1|1
    using namespace std;
    typedef long long ll;
    const int maxn=500010;
    struct node
    {
    	int val,org;
    }p[maxn];
    int n,m,nm;
    ll ans;
    int f[maxn],s[maxn],v[maxn],ps[maxn<<2];
    bool cmp(const node &a,const node &b)
    {
    	return a.val<b.val;
    }
    inline void updata(int x)
    {
    	for(int i=x;i<=nm;i+=i&-i)	s[i]++;
    }
    inline int query(int x)
    {
    	int i,ret=0;
    	for(i=x;i;i-=i&-i)	ret+=s[i];
    	return ret;
    }
    inline int MX(int a,int b)
    {
    	return v[a]<v[b]?a:b;
    }
    void build(int l,int r,int x)
    {
    	if(l==r)
    	{
    		ps[x]=l;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(l,mid,lson),build(mid+1,r,rson);
    	ps[x]=MX(ps[lson],ps[rson]);
    }
    int query(int l,int r,int x,int a,int b)
    {
    	if(a<=l&&r<=b)	return ps[x];
    	int mid=(l+r)>>1;
    	if(b<=mid)	return query(l,mid,lson,a,b);
    	if(a>mid)	return query(mid+1,r,rson,a,b);
    	return MX(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
    }
    void updata(int l,int r,int x,int a)
    {
    	if(l==r)	return ;
    	int mid=(l+r)>>1;
    	if(a<=mid)	updata(l,mid,lson,a);
    	else	updata(mid+1,r,rson,a);
    	ps[x]=MX(ps[lson],ps[rson]);
    }
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	n=rd(),m=rd();
    	int i,a,b,c;
    	for(i=1;i<=n;i++)	p[i].val=rd(),p[i].org=i;
    	sort(p+1,p+n+1,cmp);
    	for(i=1;i<=n;i++)
    	{
    		if(p[i].val>p[i-1].val)	nm++;
    		v[p[i].org]=nm;
    	}
    	for(i=n;i;i--)	f[i]=query(v[i]-1),ans+=f[i],updata(v[i]);
    	build(1,n,1);
    	printf("%lld
    ",ans);
    	for(i=1;i<=m;i++)
    	{
    		a=rd(),c=v[a];
    		if(c!=1<<30)
    		{
    			while(1)
    			{
    				b=query(1,n,1,a,n);
    				if(v[b]>c)	break;
    				ans-=f[b],v[b]=1<<30,updata(1,n,1,b);
    			}
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }//6 2 160 163 164 161 167 160 2 3 
  • 相关阅读:
    处理缺失值
    数据清理
    数据聚合
    ajax动态生成table
    MangeEmpHashMap
    Arraylist的雇员管理操作
    jsp获取一个对象和list对象
    Controller比较两个对象discs、outlets中的元素是否相等。相同则相应的checkbox为checked
    限制input text输入的类型(数字,字母,小数点)
    联合主键的映射运用
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7535713.html
Copyright © 2011-2022 走看看