Problem Description
玩了一天,小A又带着他的小伙伴们来到了当地的奇异旅馆。
这个旅馆共有n层,每层分别有ai个床位。
由于没有电梯,大家都希望尽可能住在较低的楼层。
现在小A提出了q个操作,操作分为两种:
1.从第xi层开始向上安置numi个小伙伴住宿。
2.询问前ki层一共已经安置的小伙伴数目。
假设一开始每层楼的床位都是未被使用的,
且若操作1中xi层及以上的房间无法容纳所要安置的人,
则尽可能多地安置,剩余部分忽略。
Input
输入数据的第一行是一个整数T,表示测试实例的个数,保证T<=30。
对于每组测试样例,第一行给出n和q。(1<=n<=105,1<=q<=105)
接下来一行共有n个整数ai。(1<=ai<=109)
接下来共有q行,每行表示一个操作。
第一种操作的给出形式为:1 xinumi。(1<=xi<=n,1<=numi<=109)
第二种操作的给出形式为:2 ki。(1<=ki<=n)
题目保证n>=50000且q>=50000的数据组数不超过5组。
Output
每组样例中,
对于第一种操作,若xi层及以上的房间无法容纳所要安置的人,输出“overflow”.
对于第二种操作,输出所询问的值。
每个输出数据占一行,且每组数据后输出一个空行。
Sample Input
1
3 5
2 3 5
1 1 4
2 2
1 2 3
2 2
1 3 10
Sample Output
4
5
overflow
【思路】
显然对于这么大数据范围,暴力不可行。我们考虑优化的方法。
首先,对于第一种操作,我们肯定是从低往高依次安排,但到后面一定存在一种情况,开始的一段都已经住满,没必要遍历了。于是我们考虑用并查集,将相邻的住满的楼层“连接起来”,然后每次进行操作时,我们便可以快速找到第一个空的楼层。
对于第二种操作,我们用树状数组维护前缀和即可。
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)
typedef long long ll;
const int maxn = 100005;
const ll mod = 1e9+7;
const ll INF = 0x3f3f3f3f;
const double eps = 1e-9;
int a[maxn];
int now[maxn];
int pre[maxn];
ll tree[maxn];
int lowbit(int x)
{
return x&(-x);
}
void add(int pos,ll val)
{
while(pos<maxn)
{
tree[pos]+=val;
pos+=lowbit(pos);
}
}
ll query(int pos)
{
ll ans=0;
while(pos>0)
{
ans+=tree[pos];
pos-=lowbit(pos);
}
return ans;
}
int dfs(int x)
{
int t,r=x;
while(pre[x]!=x)
{
x=pre[x];
}
while(r!=x)
{
t=pre[r];
pre[r]=x;
r=t;
}
return x;
}
void join(int a,int b)
{
int A=dfs(a);
int B=dfs(b);
if(A>B)
{
pre[B]=A;
}
else pre[A]=B;
}
int main()
{
/*freopen("c://ccpc//problem 1002 data.txt","r",stdin);
freopen("c://ccpc//problem 1002 results.txt","w",stdout);*/
int n,q;
int op,pos,w;
rush()
{
scanf("%d%d",&n,&q);
mst(now,0);
mst(tree,0);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
pre[i]=i;
}
pre[n+1]=n+1;
for(int i=0; i<q; i++)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&pos,&w);
while(w>0)
{
pos=dfs(pos);
if(pos==n+1)
{
puts("overflow");
break;
}
if(a[pos]-now[pos]>w)
{
now[pos]+=w;
add(pos,w);
w=0;
}
else
{
w-=(a[pos]-now[pos]);
add(pos,a[pos]-now[pos]);
now[pos]=a[pos];
join(pos,pos+1);
}
}
}
else if(op==2)
{
scanf("%d",&pos);
ll ans=query(pos);
printf("%I64d\n",ans);
}
}
puts("");
}
return 0;
}