HDU 3950 线段树

#include<iostream>
#include<cstring>
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<deque>
#include<list>
#include<algorithm>
#include<stdio.h>
#include<iomanip>

#define rep(i,n) for(int i=0;i<n;++i)
#define fab(i,a,b) for(int i=a;i<=b;++i)
#define fba(i,b,a) for(int i=b;i>=a;--i)
#define PB push_back
#define INF 0x3f3f3f3f
#define MP make_pair
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define sf scanf
#define pf printf
#define LL long long
#define lowbit(x) x&-x
const int N=51005;
using namespace std;
typedef pair<int,int>PII;
int n,Q;
int C[N];
set<int>S[N];
int ed[N],st[N<<2],len[N<<2];
int stlen,edlen;
void build(int l,int r,int rt){
    st[rt]=INF;
    if(l==r)S[l].clear();
    else{
        int m=(l+r)>>1;
        build(lson);
        build(rson);
    }
}

void add(int x,int d){
    while(x<=n){
        C[x]+=d;
        x+=lowbit(x);
    }
}
int sum(int x){
    int ret=0;
    while(x){
        ret+=C[x];
        x-=lowbit(x);
    }
    return ret;
}

  int Kth(int k){
     int ind=0;
     for(int i=20;i>=0;i--){
        ind^=(1<<i);
        if(ind<n&&k>C[ind])k-=C[ind];
        else ind^=(1<<i);
     }
     return ind+1;
  }

/*int Kth(int k){
    int L=0,R=n;
    while(L+1<R){
       int M=L+(R-L)/2;
       if(sum(M)>=k)R=M;
       else L=M;
    }
    return R;
}*/
void init(){
   sf("%d%d",&n,&Q);
   memset(C,0,sizeof C);
   build(1,n,1);
   stlen=edlen=n;
}
void push_up(int rt){
    if(st[rt<<1]<st[rt<<1|1]){
        st[rt]=st[rt<<1];
        len[rt]=len[rt<<1];
    }else{
        st[rt]=st[rt<<1|1];
        len[rt]=len[rt<<1|1];
    }
}
void update(int v,int p,bool add,int l,int r,int rt){
    if(l==r){
       if(add)S[l].insert(v);
       else S[l].erase(v);
       if(S[l].size()==0)st[rt]=INF;
       else{
           st[rt]=*(S[l].begin());
           len[rt]=l;
       }
    }else{
        int m=(l+r)>>1;
        if(p<=m)update(v,p,add,lson);
        else update(v,p,add,rson);
        push_up(rt);
    }
}
PII qurry(int L,int R,int l,int r,int rt){
    if(L<=l&&r<=R) return MP(st[rt],len[rt]);
    else{
        int m=(l+r)>>1;
        PII ret1=MP(INF,0),ret2=MP(INF,0);
        if(L<=m)ret1=qurry(L,R,lson);
        if(R>m)ret2=qurry(L,R,rson);
        if(ret1.first<ret2.first)return ret1;
        else return ret2;
    }
}
//guarteen can get
int getst(int st,int len,int m,int a,int b){
    int ed=st+len-1;
    return max(ed-m-b+1,st);
}
void solve(){
    while(Q--){
        char op[10];
        sf("%s",op);
        if(op[0]==‘A‘){
            int m,a,b;
            sf("%d%d%d",&m,&a,&b);
            if(stlen>=m){
               if(stlen==n){
                   ed[1]=m;
                   add(1,1);
                   stlen=0;
                   edlen-=m;
                   pf("%d\n",1);
               }else{
                   int id=getst(1,stlen,m,a,b);
                   ed[id]=id+m-1;
                   add(id,1);
                   pf("%d\n",id);
                   if(ed[id]+1<=stlen)update(ed[id]+1,stlen-ed[id],1,1,n,1);
                   stlen=id-1;
               }
            }else{
               PII ret=qurry(m,m+a+b,1,n,1);
               if(ret.first!=INF){
                    update(ret.first,ret.second,0,1,n,1);
                    int id=getst(ret.first,ret.second,m,a,b);
                    ed[id]=id+m-1;
                    add(id,1);
                    pf("%d\n",id);
                    int len=id-1-ret.first+1;
                    int p=ret.first;
                    if(ret.first<=id-1)update(p,len,1,1,n,1);
                    p=ed[id]+1;
                    len=ret.first+ret.second-1;
                    if(p<=len)update(p,len-p+1,1,1,n,1);

               }else{
                  if(edlen<m)pf("-1\n");
                  else{
                      int id=n-edlen+1;
                      ed[id]=id+m-1;
                      edlen=n-ed[id];
                      add(id,1);
                      pf("%d\n",id);
                  }
               }
            }
        }else{
            int k;
            sf("%d",&k);
            int sumn=sum(n);
            if(k>sumn||k<=0)continue;
            int id=Kth(k);
            int id1=1;
            if(k>1)id1=ed[Kth(k-1)]+1;
            int len1=id-id1;
            if(len1>0&&id1!=1)update(id1,len1,0,1,n,1);

            int id2=n;
            int len2=0;
            if(k<sumn){
                id2=Kth(k+1)-1;
                len2=id2-ed[id];
            }
            if(len2>0&&id2!=n)update(ed[id]+1,len2,0,1,n,1);

            if(id1!=1&&id2!=n)update(id1,id2-id1+1,1,1,n,1);
            if(id1==1)stlen=id2;
            if(id2==n)edlen=n-id1+1;
            add(id,-1);
        }
    }
}
int main(){
    int T;sf("%d",&T);
    rep(cas,T){
        init();
        pf("Case #%d:\n",cas+1);
        solve();
    }
    return 0;
}
时间: 2025-01-09 09:22:04

HDU 3950 线段树的相关文章

HDU 4893 线段树裸题

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2512    Accepted Submission(s): 751 Problem Description Recently, Doge got a funny birthday present from his new friend, Pro

HDU 4902 线段树(区间更新)

Nice boat Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 353    Accepted Submission(s): 169 Problem Description There is an old country and the king fell in love with a devil. The devil alw

hdu 4893 线段树 --- 也是两个变 类似双标记

http://acm.hdu.edu.cn/showproblem.php?pid=4893 开始的时候,我按双标记,WA了一下午,搞不定,我是用的两个标记add--表示当前结点中有值发生变化,flag,斐波那契的懒惰标记,但是估计是我自己处理的有问题,一直不对 参考了别人的代码,写法还是很不错的,Add变量维护的是,完全变成Fibonacci的时候的和,---回头我再重新写一遍 #include <cstdio> #include <cstring> #include <a

HDU 4902 线段树||暴力

给定一个序列,两种操作 1:把一段变成x. 2:把一段每个数字,如果他大于x,就变成他和x的gcd,求变换完后,最后的序列. 线段树解法:用lazy标记下即可,优化方法还是很巧妙的, Accepted 4902 515MS 3308K 1941 B C++ #include "stdio.h" #include "string.h" struct node { int l,r,x;// 在叶子节点代表值,树节点代表成端更新的lazy操作. }data[400010]

HDU 4302 线段树单点更新,维护区间最大最小值

http://acm.hdu.edu.cn/showproblem.php?pid=4302 Problem Description Holedox is a small animal which can be considered as one point. It lives in a straight pipe whose length is L. Holedox can only move along the pipe. Cakes may appear anywhere in the p

HDU 3397 线段树 双懒惰标记

这个是去年遗留历史问题,之前思路混乱,搞了好多发都是WA,就没做了 自从上次做了大白书上那个双重懒惰标记的题目,做这个就思路很清晰了 跟上次大白上那个差不多,这个也是有一个sets标记,代表这个区间全部置为0或者1,没有置位的时候为-1 还有个rev标记,代表翻转操作,0代表当前不翻,1代表当前翻 要注意一下优先级,发现有不同的弄法,我是这个弄得,有set操作的时候,set标记设值,并把当前节点的rev标记设为0,因为不管要不要rev,当前set操作肯定直接覆盖了 rev操作不改变set操作,在

hdu 2795 线段树--点更新

http://acm.hdu.edu.cn/showproblem.php?pid=2795 多校的第一场和第三场都出现了线段树,比赛期间没做,,这两天先做几道热身下,然后31号之前把那两道多校的线段树都搞了,这是一道热身题 关键是建模: 首先一定看清楚题目构造的场景,看有什么特点--------会发现,如果尽量往左上放置的话,那么由于 the i-th announcement is a rectangle of size 1 * wi.,完全可以对h建立线段树,表示一行,结点里的l,r就表示

HDU 1698 线段树(区间染色)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 16255    Accepted Submission(s): 8089 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing f

HDU 3642 线段树+离散化+扫描线

题意:给你N个长方体的左下角和右上角坐标,问你空间中有多少体积是被大于两个不同的立方体覆盖的.x,y~10^6 z~500 考虑到给的z比较小,所以可以直接枚举z,然后跑二维的扫描线就好. 关于处理被不同的线段覆盖三次的问题,可以维护四个信息,cnt,once,twice,more,然后相互推出结果就好. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #