牛客练习赛91-监狱逃亡-(思维+类比逆序对+树状数组)

D

题意:
就是给你三层的地图,3行n列,现在你在1,1处,每次可以往右走一次和往下走一次,问你走到3,n的时候权值>=0的不同方法一共有多少种,同时取模。

思考:
昨天看了看,我以为还是以前做过的那个直接枚举状态的题呢,但是这个状态1e9…。但是发现只有三行,而且还要走到n,m很明显,推一下式子就行了。没两次下降的位置i,j。那么就是sum1[i]+sum2[j]-sum2[i-1]+sum3[n]-sum3[j-1]>=0;发现这怎么办呢,i和j是不同的。所以分开看一下,转化成sum2[j]-sum3[j-1]+sum3[n]>=sum2[i-1]-sum1[i];也就是当枚举到j的时候,有多少i小于他。正好也符合我们的假设是i<=j的情况。但是我卡到这里了,发现这怎么办?其实这只是不同的位置的时候不同的值,直接放进去就行了。从前往后放,先放va[i],在求一下query(vb[i])就行了。

代码:

int T,n,m,k;
int va[N],vb[N],vc[N];
int sum1[N],sum2[N],sum3[N];
int tr[N],R = 1e6+5;

vector<int > v;

int bit(int x)
{
	return x&(-x);
}

void update(int x,int value)
{
	while(x<=R)
	{
		tr[x] += value;
		x += bit(x);
	}
}

int query(int x)
{
	int sum = 0;
	while(x)
	{
		sum += tr[x];
		x -= bit(x);
	}
	return sum;
}

int get(int x)
{
	return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}

signed main()
{
	IOS;
	cin>>n;
	for(int i=1;i<=3;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>vc[j];
			if(i==1) sum1[j] = sum1[j-1]+vc[j];
			if(i==2) sum2[j] = sum2[j-1]+vc[j];
			if(i==3) sum3[j] = sum3[j-1]+vc[j];
		}
	}
	for(int i=1;i<=n;i++)
	{
		va[i] = sum2[i-1]-sum1[i];
		vb[i] = sum2[i]-sum3[i-1]+sum3[n];
		v.pb(va[i]);v.pb(vb[i]);
	}
	sort(v.begin(),v.end());
	v.erase(unique(v.begin(),v.end()),v.end());
	int ans = 0;
	for(int i=1;i<=n;i++)
	{
		update(get(va[i]),1);
		ans = (ans+query(get(vb[i])))%mod;
	}
	ans = (ans%mod+mod)%mod;
	cout<<ans;
	return 0;
}

总结:
多多思考呀,不要想的太复杂。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值