涨姿势之区间刷新
TimeLimit:2000MS Memo
View Code
ryLimit:128MB
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 7 typedef long long ll; 8 const int N=1e6+6; 9 10 int arr[N],sum[N]; 11 int t,n,m,s,w; 12 13 int main(){ 14 ios::sync_with_stdio(false); 15 cin>>t; 16 while(t--){ 17 memset(arr,0,sizeof(arr)); 18 memset(sum,0,sizeof(sum)); 19 cin>>n>>m>>s>>w; 20 while(m--){ 21 int x,y; 22 cin>>x>>y; 23 arr[x]++,arr[y+1]--; 24 } //这里优化了一下时间复杂度 25 for(int i=1;i<=n;i++){ 26 arr[i]+=arr[i-1]; 27 } 28 for(int i=1;i<=n;i++){ //求前缀和 29 sum[i]=sum[i-1]+arr[i]; 30 } 31 // for(int i=1;i<=n;i++) cout << sum[i] << endl; 32 ll res=0,l=1,r=1; //双指针从一开始 33 for(int i=1;i<=n;i++){ 34 while(r<i&&sum[i]-sum[r]>=w){ 35 r++; 36 } 37 while(l-1<r-1&&sum[r-1]-sum[l-1]>=w&&sum[i]-sum[l-1]>=s){ //l-1是符合的 38 l++; 39 } 40 if(l-2<r-1&&sum[i]-sum[r-1]>=w&&sum[r-1]-sum[l-2]>=w&&sum[i]-sum[l-2]>=s){ 41 res+=l-1; 42 // cout << " " << res << " " << endl; 43 } 44 } 45 cout << res << endl; 46 } 47 return 0; 48 }
64-bit integer IO format:%lld
已解决 | 点击收藏 | 已有4人收藏了本题
Problem Description
Value_Dragon是一个有钱人。快过年了,所以他准备发红包。但是他发红包的方式很奇葩。他让n个人排成一排。每次选择1-n中的一段区间[l,r]发,给区间中的每一个人一块钱。就这样发了m次红包。发完后他想知道在[1,n]的子区间中有多少个区间满足以下要求
-
这个区间得到钱的总数不少于s
-
这个区间可以被分成两个不相交的子区间且每个子区间得到的钱的总数不小于w
(注:一个区间的子区间包括自己本身)
防坑提醒,长度为1的区间比如[1,1],是不能被拆成两个子区间的
Input
第一行是一个整数T代表数据的组数。
接下来有T组数据
每组数据开头有四个整数,分别代表n m s w
接下来m行,每行是是两个数l,r代表区间[l,r]的左右端点
其中T<=10
n<=10^6,m<=10^5
0<l<=r<=n
0<=w<=s<10^8
Output
对于每组数据输出一行,代表符合要求的区间个数
SampleInput
4 1 0 0 0 1000000 0 0 0 1000000 1 0 0 1 1000000 10 10 20 14 2 10 5 9 5 5 6 8 2 6 9 10 6 7 6 10 4 5 5 7
SampleOutput
0 499999500000 499999500000 8