hdu6315 Naive Operations
题目链接:戳我
给你两个序列a,b,其中a初始是全空的,b是一个排列。
现在有两种操作:
1、给一个区间的a数组加上1
2、求一个区间\(\sum a[i]/b[i]\)
区间操作想到用数据结构维护。
我们可以知道,\(a[i]/b[i]\)只有在a[i]增加够一个b[i]的时候才会多1的贡献,但是我们再增加a[i]的时候和b[i]进行比较比较麻烦(但其实也应该是可以做的),所以我们考虑转化成b[i]-1。
如果b[i]的区间最小值大于1,直接区间减法即可。如果不是,那么寻找那个值为1的,把它改成初始b[i]。
具体见代码:
#include
#include
#include
#include
#include
#define MAXN 100010
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48); ch=getchar();}
return x*f;
}
int n,q;
int a[MAXN],b[MAXN];
struct Node{long long sum,valb,minn,tag;}t[MAXN<<2];
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
inline void push_up(int x)
{
t[x].minn=min(t[ls(x)].minn,t[rs(x)].minn);
t[x].sum=t[ls(x)].sum+t[rs(x)].sum;
}
inline void push_down(int x)
{
if(t[x].tag)
{
t[ls(x)].tag+=t[x].tag;
t[rs(x)].tag+=t[x].tag;
t[ls(x)].minn-=t[x].tag;
t[rs(x)].minn-=t[x].tag;
t[x].tag=0;
}
}
inline void build(int x,int l,int r)
{
t[x].tag=t[x].sum=0;
if(l==r)
{
t[x].minn=t[x].valb=b[l];
t[x].sum=0;
return;
}
int mid=(l+r)>>1;
build(ls(x),l,mid);
build(rs(x),mid+1,r);
push_up(x);
}
inline void update(int x,int l,int r,int ll,int rr)
{
if(ll<=l&&r<=rr&&t[x].minn>1)
{
t[x].tag++;
t[x].minn--;
return;
}
if(l==r&&t[x].minn==1)
{
t[x].sum++;
t[x].minn=t[x].valb;
t[x].tag=0;
return;
}
int mid=(l+r)>>1;
push_down(x);
if(ll<=mid) update(ls(x),l,mid,ll,rr);
if(mid>1;
push_down(x);
long long cur_ans=0;
if(ll<=mid) cur_ans+=query(ls(x),l,mid,ll,rr);
if(mid>str;
// cout<