Codeforces Round #510 (Div. 2) D. Petya and Array

朱雀 2022-05-15 18:24 299阅读 0赞

题目:点击打开链接 题意:给定一个数组,问有多少个不同的区间[l,r] (l<=r)使得区间和小于给定的数t。 分析:先求个前缀和,则问题转化为所有满足sum[i]-sum[j]<t(j<=i)的区间个数,原式可变形为-sum[j]<t-sum[i],所以可以用一颗红黑树维护-sum[j](点击查看红黑树的库实现博客),然后用order_of_key查询t-sum[i]的rank,这个rank其实就是右端点为i时左端点满足的个数。总复杂度nlog(n),其中遍历数组为o(n),红黑树查询为log(n)。

注:由于红黑树里不能有相同元素,所以这里让红黑树维护pair<-sum[i],index>,其中index为下标i.这样就能保证能存储相同的-sum[i].看红黑树实现起来多简短!

补充:这题也可以用树状数组+map做,也是求前面前缀和大于sum[i]-t的个数,和树状数组求逆序数的思想一样,因为有负数,所以把前缀和数组统一加上一个大数变成正数,这个数要大于2e14,不过奇怪的是我把这个数设成奇数就超内存了,设成偶数就ac了,感觉用标准的离散化更保险。

参考博客https://blog.csdn.net/qq_40791842/article/details/82780345。 代码一(红黑树解法):

  1. #pragma comment(linker, "/STACK:102400000,102400000")
  2. #include<unordered_map>
  3. #include<unordered_set>
  4. #include<algorithm>
  5. #include<iostream>
  6. #include<fstream>
  7. #include<complex>
  8. #include<cstdlib>
  9. #include<cstring>
  10. #include<cassert>
  11. #include<iomanip>
  12. #include<string>
  13. #include<cstdio>
  14. #include<bitset>
  15. #include<vector>
  16. #include<cctype>
  17. #include<cmath>
  18. #include<ctime>
  19. #include<stack>
  20. #include<queue>
  21. #include<deque>
  22. #include<list>
  23. #include<set>
  24. #include<map>
  25. #include <ext/pb_ds/tree_policy.hpp>
  26. #include <ext/pb_ds/assoc_container.hpp>
  27. using namespace std;
  28. using namespace __gnu_pbds;
  29. #define pt(a) cout<<a<<endl
  30. #define debug test
  31. #define mst(ss,b) memset((ss),(b),sizeof(ss))
  32. #define rep(i,a,n) for (int i=a;i<=n;i++)
  33. #define per(i,a,n) for (int i=n-1;i>=a;i--)
  34. #define pii pair<int,int>
  35. #define fi first
  36. #define se second
  37. #define ll long long
  38. #define ull unsigned long long
  39. #define pb push_back
  40. #define mp make_pair
  41. #define inf 0x3f3f3f3f
  42. #define eps 1e-10
  43. #define PI acos(-1.0)
  44. #define lb(x) (x&(-x))
  45. #define RBT tree<pair<ll,int>, null_type, less<pair<ll,int> >, rb_tree_tag, tree_order_statistics_node_update>
  46. const ll mod = 1e9+7;
  47. const int N = 1e6+10;
  48. ll qp(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
  49. int to[4][2]={
  50. {-1,0},{1,0},{0,-1},{0,1}};
  51. ll n,t,x;
  52. int main() {
  53. ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
  54. while(~scanf("%lld%lld",&n,&t)) {
  55. RBT rbt;
  56. rbt.insert({0,0});
  57. ll ans=0,sum=0;
  58. for(int i=1;i<=n;i++) {
  59. scanf("%lld",&x);
  60. sum-=x;
  61. ans+=rbt.order_of_key({t+sum,0});
  62. rbt.insert({sum,i});
  63. }
  64. printf("%lld\n",ans);
  65. }
  66. return 0;
  67. }

代码二(树状数组解法):

  1. #pragma comment(linker, "/STACK:102400000,102400000")
  2. #include<unordered_map>
  3. #include<unordered_set>
  4. #include<algorithm>
  5. #include<iostream>
  6. #include<fstream>
  7. #include<complex>
  8. #include<cstdlib>
  9. #include<cstring>
  10. #include<cassert>
  11. #include<iomanip>
  12. #include<string>
  13. #include<cstdio>
  14. #include<bitset>
  15. #include<vector>
  16. #include<cctype>
  17. #include<cmath>
  18. #include<ctime>
  19. #include<stack>
  20. #include<queue>
  21. #include<deque>
  22. #include<list>
  23. #include<set>
  24. #include<map>
  25. using namespace std;
  26. #define pt(a) cout<<a<<endl
  27. #define debug test
  28. #define mst(ss,b) memset((ss),(b),sizeof(ss))
  29. #define rep(i,a,n) for (int i=a;i<=n;i++)
  30. #define per(i,a,n) for (int i=n-1;i>=a;i--)
  31. #define pii pair<int,int>
  32. #define fi first
  33. #define se second
  34. #define ll long long
  35. #define ull unsigned long long
  36. #define pb push_back
  37. #define mp make_pair
  38. #define inf 0x3f3f3f3f
  39. #define eps 1e-10
  40. #define PI acos(-1.0)
  41. #define lb(x) (x&(-x))
  42. const ll mod = 1e9+7;
  43. const int N = 1e6+10;
  44. ll qp(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
  45. int to[4][2]={
  46. {-1,0},{1,0},{0,-1},{0,1}};
  47. ll n,t,x,mx=2e14+10,a[N];
  48. map<ll,int> ma;
  49. void upd(ll x) {
  50. while(x<=2*mx) {
  51. ma[x]++;
  52. x+=lb(x);
  53. }
  54. }
  55. int gs(ll x) {
  56. int rs=0;
  57. while(x>0) {
  58. rs+=ma[x];
  59. x-=lb(x);
  60. }
  61. return rs;
  62. }
  63. int main() {
  64. ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
  65. cin>>n>>t;
  66. for(int i=1;i<=n;i++) cin>>a[i],a[i]+=a[i-1];
  67. upd(mx);
  68. ll ans=0;
  69. for(int i=1;i<=n;i++) {
  70. ans+=i-gs(a[i]+mx-t);
  71. upd(a[i]+mx);
  72. }
  73. cout<<ans<<endl;
  74. return 0;
  75. }

发表评论

表情:
评论列表 (有 0 条评论,299人围观)

还没有评论,来说两句吧...

相关阅读