我太菜了,这场打了300多名,差一点就GG了.
题意
给一个序列,问有多少区间的和小于t.
题解
对序列求前缀和
,可以发现问的就是有多少
.
想起来曾经做过类似的题,但是突然不知道怎么推了,觉得应该是个类似逆序对的题.
结果机房大佬纷纷写平衡树,我只好膜拜他们.
如果用数据结构维护,很简单,每次询问前面有多少个数大于
,插入
,全部相加即可,用线段树,树状数组,平衡树都可以维护.
然后我们思考分治法.
将序列分为两半,每一半分别排序,然后每一半里自己的答案可以递归统计,而两半之间的答案可以用尺取法解决.
因为两半的前缀和都是单调的,所以用
从左边开始扫,找到最小的
使得
.
每次都这样统计,复杂度
.
#include<bits/stdc++.h> //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
int x=0,f=1;char c=gc();
for (;!isdigit(c);c=gc()) f^=c=='-';
for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
return f?x:-x;
}
template <typename mitsuha>
inline bool read(mitsuha &x){
x=0;int f=1;char c=gc();
for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
if (!~c) return 0;
for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
return x=f?x:-x,1;
}
template <typename mitsuha>
inline int write(mitsuha x){
if (!x) return 0&pc(48);
if (x<0) x=-x,pc('-');
int bit[20],i,p=0;
for (;x;x/=10) bit[++p]=x%10;
for (i=p;i;--i) pc(bit[i]+48);
return 0;
}
inline char fuhao(){
char c=gc();
for (;isspace(c);c=gc());
return c;
}
}using namespace chtholly;
using namespace std;
const int yuzu=2e5;
typedef ll fuko[yuzu|10];
fuko a;
ll t,ans;
void merge(int l,int r){
if (l==r) return;
int mid=l+r>>1,i=l,j=mid+1;
merge(l,mid),merge(mid+1,r);
for (;i<=mid;++i,ans+=j-mid-1)
for (;j<=r&&a[j]<t+a[i];) ++j;
inplace_merge(a+l,a+mid+1,a+r+1);
}//归并排序
int main(){
int i,n=read();
for (read(t),i=1;i<=n;++i) a[i]=read()+a[i-1];
merge(0,n),write(ans),pl;
}
/*
雨霖铃 柳永
寒蝉凄切,对长亭晚,骤雨初歇.都门帐饮无绪,留恋处,兰舟催发.
执手相看泪眼,竟无语凝噎.念去去,千里烟波,暮霭沉沉楚天阔.
多情自古伤离别,更那堪,冷落清秋节!今宵酒醒何处?杨柳岸,晓风残月.
此去经年,应是良辰好景虚设.便纵有千种风情,更与何人说!
*/
谢谢大家.