HDU 5412 CRB and Queries【整体二分+树状数组】

来源:互联网 发布:淘宝网服饰女毛衣 编辑:程序博客网 时间:2024/05/19 13:58

裸动态区间第K大
据说树套树很容易MLE,要有很厉害的姿势才能够
于是就只能用整体二分

代码有加注释,学自这儿

//      whn6325689//      Mr.Phoebe//      http://blog.csdn.net/u013007900#include <algorithm>#include <iostream>#include <iomanip>#include <cstring>#include <climits>#include <complex>#include <fstream>#include <cassert>#include <cstdio>#include <bitset>#include <vector>#include <deque>#include <queue>#include <stack>#include <ctime>#include <set>#include <map>#include <cmath>#include <functional>#include <numeric>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define eps 1e-9#define PI acos(-1.0)#define INF 0x3f3f3f3f#define LLINF 1LL<<62#define speed std::ios::sync_with_stdio(false);typedef long long ll;typedef unsigned long long ull;typedef long double ld;typedef pair<ll, ll> pll;typedef complex<ld> point;typedef pair<int, int> pii;typedef pair<pii, int> piii;typedef vector<int> vi;#define CLR(x,y) memset(x,y,sizeof(x))#define CPY(x,y) memcpy(x,y,sizeof(x))#define clr(a,x,size) memset(a,x,sizeof(a[0])*(size))#define cpy(a,x,size) memcpy(a,x,sizeof(a[0])*(size))#define mp(x,y) make_pair(x,y)#define pb(x) push_back(x)#define lowbit(x) (x&(-x))#define MID(x,y) (x+((y-x)>>1))#define ls (idx<<1)#define rs (idx<<1|1)#define lson ls,l,mid#define rson rs,mid+1,r#define root 1,1,ntemplate<class T>inline bool read(T &n){    T x = 0, tmp = 1;    char c = getchar();    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();    if(c == EOF) return false;    if(c == '-') c = getchar(), tmp = -1;    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    n = x*tmp;    return true;}template <class T>inline void write(T n){    if(n < 0)    {        putchar('-');        n = -n;    }    int len = 0,data[20];    while(n)    {        data[len++] = n%10;        n /= 10;    }    if(!len) data[len++] = 0;    while(len--) putchar(data[len]+48);}//-----------------------------------const int MAXN=400010;int val[MAXN],discrete[MAXN],ans[MAXN],bit[MAXN];int n,m,tot,cnt,timestamp;struct Node{    int id,l,r,k;    Node(){}    Node(int id,int l,int r,int k):id(id),l(l),r(r),k(k){}}q[MAXN],q1[MAXN],q2[MAXN];//用树状数组标记修改操作在i处插入了几个数//修改操作可以认为是 删除操作 + 插入操作 void update(int i,int val){    for(;i<=n;i+=lowbit(i))        bit[i]+=val;}int getsum(int i){    int sum=0;    for(;i;i-=lowbit(i))        sum+=bit[i];    return sum;}void solve(int h,int t,int l,int r)//h~t为操作,l~r为数 {    if(l==r)    {        for(int i=h;i<=t;i++)            if(q[i].id)                ans[q[i].id]=discrete[l];        return;    }    int mid=MID(l,r),i1=0,i2=0;//mid为数的中间值(有的题目用的是真实的数值)     int rnk=0;    for(int i=h;i<=t;i++)    {        if(q[i].id==0)        {            if(q[i].k<=mid)            {                update(q[i].l,q[i].r);  //q[i].l位置插入或者删除一个数                 q1[i1++]=q[i];             }            else            {                q2[i2++]=q[i];             }        }        else        {            rnk=getsum(q[i].r)-getsum(q[i].l-1);    //如果在(q[i].l~q[i].r)这段区间内的数个数小于查询的第k大,那么第k大必然是在前面那段             if(q[i].k<=rnk)            {                q1[i1++]=q[i];            }            else            {                q[i].k-=rnk;        //如果在后半段,则因为分治,所以要减去前半段                 q2[i2++]=q[i];             }        }    }    for(int i=0;i<i1;i++)        if(q1[i].id==0)            update(q1[i].l,-q1[i].r);    memcpy(q+h,q1,sizeof(Node)*i1);    memcpy(q+h+i1,q2,sizeof(Node)*i2);    solve(h,h+i1-1,l,mid);    solve(h+i1,t,mid+1,r); } int main(){    while(read(n))    {        tot=0,cnt=0,timestamp=0;        for(int i=1;i<=n;i++)        {            read(val[i]);            discrete[++cnt]=val[i];            q[++tot]=Node(0,i,1,val[i]);    //初始化不为0的情况,可以认为是插入         }         read(m);        for(int i=1,op,l,r,k;i<=m;i++)        {            read(op),read(l),read(r);            if(op==1)            {                discrete[++cnt]=r;                q[++tot]=Node(0,l,1,r);                q[++tot]=Node(0,l,-1,val[l]);                val[l]=r;            }            else            {                read(k);                q[++tot]=Node(++timestamp,l,r,k);            }        }         sort(discrete+1,discrete+cnt+1);        cnt=unique(discrete,discrete+cnt+1)-discrete-1;        for(int i=1;i<=tot;i++)        {            if(q[i].id==0)            {                q[i].k=lower_bound(discrete+1,discrete+cnt+1,q[i].k)-discrete;            }        }        solve(1,tot,1,cnt);        for(int i=1;i<=timestamp;i++)        {            write(ans[i]),putchar('\n');        }    }    return 0;} 
1 0
原创粉丝点击