签到5分钟,挂机2小时 然后掉分
想了两个小时B,想着用树状数组维护数量,但实际上他不动态的去更改的话,似乎用个数组,最多再统计一下前缀和,即可实现树状数组的功能,太假了。后来想的set,pair。
总而言之,没把问题想透。
B New Year and Ascent Sequence
其实对一个序列而言,如果他存在一个递增的子序列,那么所有别的序列+这个序列合成产生的答案都是满足的。所以这些序列对答案的贡献n都是满的。
我们只对另一些序列进行操作,对于那些不存在递增子序列的序列,我们给他标记,并且统计他们最大值出现的次数。(这里我自己写烦了,如官方题解所说,这样的序列最大值肯定是第一个元素,最小值肯定是最后一个元素)
考虑从n*n中减去不满足的答案。
对这些序列的最大值出现次数求一下前缀和
最后遍历对每个不存在递增子序列的序列,减去最大值比当前序列最小值还要<= 的个数,最后得出来的就是答案了。
还有对上述序列最大值 排完序用lowerbound的做法,思想也是一样的。
1 #include <bits/stdc++.h> 2 #ifndef ONLINE_JUDGE 3 #define debug(x) cout << #x << ": " << x << endl 4 #else 5 #define debug(x) 6 #endif 7 using namespace std; 8 typedef long long ll; 9 const int MAXN=1e5+7; 10 const int INF=0x3f3f3f3f; 11 const int MOD=1e9+7; 12 13 int ma[MAXN],mi[MAXN]; 14 15 int n,m; 16 17 int arr[MAXN]; 18 19 int cnt[1100000]; 20 int flag[110000]; 21 22 int main() 23 { 24 ios::sync_with_stdio(false); 25 cin.tie(0); 26 cin>>n; 27 memset(mi,0x3f,sizeof(mi)); 28 for(int i=0,l;i<n;++i) 29 { 30 cin>>l; 31 for(int j=0;j<l;++j) 32 { 33 cin>>arr[j]; 34 if(arr[j]>mi[i]) flag[i]=1; 35 ma[i]=max(ma[i],arr[j]); 36 mi[i]=min(mi[i],arr[j]); 37 } 38 if(!flag[i]) 39 cnt[ma[i]]++; 40 } 41 ll ans=1ll*n*n; 42 for(int i=1;i<=1000000;++i) cnt[i]+=cnt[i-1]; 43 for(int i=0;i<n;++i) 44 { 45 if(!flag[i]) 46 { 47 debug(cnt[mi[i]]); 48 ans-=cnt[mi[i]]; 49 } 50 } 51 cout<<ans<<‘\n‘; 52 return 0; 53 }
有趣的计数题,感觉可以当结论记住。题意就是对n的全排列,统计所有的[l,r]使得区间内的max-min==r-l,统计这样的l,r数量。
显然对于阶乘次数的每个排列去找这样的l,r,不太现实。统计也很困难。
我们不固定fix这个排列,而是固定一个l,r,对于一个长度为len=r-l+1的区间,(选择的是数必然是一个a~a+len-1的一个排列),这区间内的数的排列顺序组合有len!个,将这个区间缩成为一个数,算上剩余的数,就是(n-len+1),也就有(n-len+1)!个。
然后从长度为n的区间中选这样连续长len区间,又有n-len+1个选法,比如说 n=3,选len=2的区间,有两种选法。
然后式子就推出来了,然后对每个len 1~n 统计答案即可。
这也tql8.
写题解希望记住!主要还是思维吧,不从排列突破,从l,r的选取突破。
1 #include <bits/stdc++.h> 2 #ifndef ONLINE_JUDGE 3 #define debug(x) cout << #x << ": " << x << endl 4 #else 5 #define debug(x) 6 #endif 7 using namespace std; 8 typedef long long ll; 9 const int MAXN=3e5+7; 10 const int INF=0x3f3f3f3f; 11 const int MOD=1e9+7; 12 13 ll fac[MAXN]; 14 ll n,m; 15 int main() 16 { 17 ios::sync_with_stdio(false); 18 cin.tie(0); 19 cin>>n>>m; 20 fac[0]=1; 21 for(int i=1;i<MAXN;++i) fac[i]=fac[i-1]*i%m; 22 ll ans=0; 23 for(ll i=1;i<=n;++i) 24 { 25 ans+=(n-i+1)*fac[i]%m*fac[n-i+1]%m; 26 ans%=m; 27 } 28 cout<<ans<<‘\n‘; 29 return 0; 30 }
原文地址:https://www.cnblogs.com/Zzqf/p/12152384.html