[luogu]1531 线段树

来源:互联网 发布:focusky for mac中文 编辑:程序博客网 时间:2024/06/13 09:18

今天整理线段树,发现了一份比较神奇的代码
不需要记录左子树的范围和右子树的范围
伪代码如下:

struct Segment{//好像不少人是这样的    int v,tag;//有的题标记都不用};

只需传递整棵树的范围:[L,R]
左子树:[L,(L+R)/2]
右子树:[(L+R)/2+1,R]
以此类推,大大地节约了空间

来一道题练练手:
luoguP1531

完整代码

#include<cstdio>#include<iostream>#define N 200010#define INF 2147483647using namespace std;struct tree{    int v;}t[4*N];int n,m,p,q,w;char c;int rd(){    char ch;    int p=0,q=1;    while((ch=getchar())<'0'||ch>'9')if(ch=='-')q=-1;    while(ch>='0'&&ch<='9')p=p*10+ch-'0',ch=getchar();    return p*q;}void add(int x,int l,int r){    if(l==r){        t[x].v+=q;        return;    }    if(p<=(l+r)/2)add(2*x,l,(l+r)/2);    else add(2*x+1,(l+r)/2+1,r);    t[x].v=max(t[2*x].v,t[2*x+1].v);}int find(int x,int l,int r){    if(l==r)return t[x].v;    if(p<=(l+r)/2)return find(2*x,l,(l+r)/2);    return find(2*x+1,(l+r)/2+1,r);}int query(int x,int l,int r){    if(p<=l&&r<=q)return t[x].v;    int ans=-INF;    if(p<=(l+r)/2)ans=max(ans,query(2*x,l,(l+r)/2));    if(q>=(l+r)/2+1)ans=max(ans,query(2*x+1,(l+r)/2+1,r));    return ans;}int main(){//    scanf("%d%d",&n,&m);    n=rd(); m=rd();    for(int i=1;i<=n;i++){//        scanf("%d",&q);        q=rd();        p=i;        add(1,1,n);    }    for(int i=1;i<=m;i++){        while((c=getchar())!='Q'&&c!='U');//        scanf("%d%d",&p,&q);        p=rd(); q=rd();        if(c=='Q')printf("%d\n",query(1,1,n));        else if((q-=find(1,1,n))>0)add(1,1,n);    }}