zoj 3279 ants 线段树+单点更新+查询下标

题目:

Ants

Time Limit: 2 Seconds       Memory Limit: 32768 KB

echo is a curious and clever girl, and she is addicted to the ants recently.

She knows that the ants are divided into many levels depends on ability, also, she finds the number of each level will change.

Now, she will give two kinds of operations as follow :

First, "p a b", the number of ants in level a change to b.

Second, "q x", it means if the ant's ability is rank xth in all ants, what level will it in?

Input

There are multi-cases, and you should use EOF to check whether it is in the end of the input. The first line is an integer n, means the number of level. (1 <= n <= 100000). The second line follows n integers, the ith integer means the number in level i. The third line is an integer k, means the total number of operations. Then following k lines, each line will be "p a b" or "q x", and 1 <= x <= total ants, 1 <= a <= n, 0 <= b. What's more, the total number of ants won't exceed 2000000000 in any time.

Output

Output each query in order, one query each line.

Sample Input

3
1 2 3
3
q 2
p 1 2
q 2

Sample Output

2
1


有不超过100000种leval  每个等级有一定数量的蚂蚁 蚂蚁总共不超过 2000000000(可以用int维护线段树) 
p a b 指 leval 为a的蚂蚁数量变成b 
q x 蚂蚁在leval排名中位列第x,求它的leval 


思路:
基础线段树,线段树数组维护蚂蚁数量,第一个操作为单点更新,第二个操作为从前向后查询返回满足条件的下标。

输入需要注意一下:

scanf("%c",&answer) 与 scanf(" %c",&answer),后者只是在%前多了个空格,似乎没有什么区别,但使用起来区别是很大的。
scanf()作单字符输入时规定只接收一个字符,但它却把回车符也作为字符对待的。这就造成程序中只有一个输入字符的scanf()语句时,问题还不大,但如果后面还跟着第二个scanf()字符输入语句,这个scanf()就把前面输入的回车符当作输入字符了。这就在输入逻辑上造成了混乱,达不到人们预期的愿望。
有了这个空格,这个空格就相当于要求输入一个空格,刚好把刚才的'\n'接收掉。之所以' '能接收'\n',是因为"%c...."中的空格是广义的,对‘\n'、'\t'都有效。而且实践证明,这个空格放在%c后面也不能达到目的。应当说,这也是比较巧妙的应用!
(参 : https://zhidao.baidu.com/question/392449587678951245.html)

当然,此处scanf(" %c",&c) + c==... 也可以用scanf("%s",c)  + c[0]=....替换



代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<ctype.h>    //tower()
#include<set>  
#include<map>  
#include<iomanip>// cout<<setprecision(1)<<fixed<<a;
#include<vector>   
#include<time.h>  
#include<assert.h>  //assert
#include<cmath>	
#include<algorithm>
#include<bitset>
#include<limits.h>
#include<stack>
#include<queue>
using namespace std;
const int maxn=100010;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1 

int n,k,a,b;
int sum[maxn<<2];
char c;

void build(int l,int r,int rt){
    if(l==r){
    	scanf("%d",&sum[rt]);
        return ;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}

void update(int a,int b,int l,int r,int rt){
    if(l==r){
        sum[rt]=b;
        return ;
    }
    int mid=(l+r)>>1;
    if(a<=mid) update(a,b,lson);
    else update(a,b,rson);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}

int query(int va,int l,int r,int rt){
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(va<=sum[rt<<1])return query(va,lson);
    else return query(va-sum[rt<<1],rson);
}

int main(){//160 MS 1848K
	while(~scanf("%d",&n)){
		build(1,n,1);
		scanf("%d",&k);
		while(k--){
			scanf(" %c",&c);//注意输入需要多一个空格
			if(c=='p'){
				scanf("%d%d",&a,&b);
				update(a,b,1,n,1);
			}
			else{
				scanf("%d",&a);
				printf("%d\n",query(a,1,n,1));
			}
		}
	}
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值