题意:
就是给你三层的地图,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;
}
总结:
多多思考呀,不要想的太复杂。