zoukankan      html  css  js  c++  java
  • 排队——树状数组

    题目描述

    每天,农夫John的N(1 <= N <= 50,000)头牛总是按同一序列排队.有一天,John决定让一些牛们玩一场飞盘比赛.他准备找一群在对列中位置连续的牛来进行比赛.但是为了避免水平悬殊,牛的身高不应该相差太大.
    John准备了Q (1 <= Q <= 180,000)个可能的牛的选择和所有牛的身高 (1 <= 身高 <= 1,000,000). 他想知道每一组里面最高和最低的牛的身高差别.
    注意: 在最大数据上, 输入和输出将占用大部分运行时间.

    输入

    第1行: N 和 Q.
    第2…N+1行: 第i+1行是第i头牛的身高.
    第N+2…N+Q+1行: 每行两个整数A和B(1 <= A <= B <= N), 表示从A到B的所有牛.

    输出

    第1…Q行: 所有询问的回答 (最高和最低的牛的身高差), 每行一个.

    样例输入

    6 3
    1
    7
    3
    4
    2
    5
    1 5
    4 6
    2 2
    

    样例输出

    6
    3
    0

    提示

    10%的数据 N,Q<=10
    30%的数据 N,Q<=2000

    找了好长时间的bug,还有好多玄学问题没有解决,耽误了好长时间一直是wa 18%
    ///尴尬的分界线…不知道够不够长先这样吧

    #pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
    #pragma GCC optimize("Ofast")
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #pragma comment(linker, "/stack:200000000")
    #pragma GCC optimize (2)
    #pragma G++ optimize (2)
    #include <bits/stdc++.h>
    #include <algorithm>
    #include <map>
    #include <queue>
    #include <set>
    #include <stack>
    #include <string>
    #include <vector>
    using namespace std;
    #define wuyt main
    typedef long long ll;
    #define HEAP(...) priority_queue<__VA_ARGS__ >
    #define heap(...) priority_queue<__VA_ARGS__,vector<__VA_ARGS__ >,greater<__VA_ARGS__ > >
    template<class T> inline T min(T &x,const T &y){return x>y?y:x;}
    template<class T> inline T max(T &x,const T &y){return x<y?y:x;}
    //#define getchar()(p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
    //char buf[(1 << 21) + 1], *p1 = buf, *p2 = buf;
    ll read(){ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();
    if(c == '-')Nig = -1,c = getchar();
    while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();
    return Nig*x;}
    #define read read()
    const ll inf = 0x3f3f3f3f;
    const int maxn = 2e5 + 7;
    const int mod = 1e9 + 7;
    #define start int wuyt()
    #define end return 0
    ll n,m;
    ll a[maxn],tree1[maxn],tree2[maxn];
    ll lowbit(ll x)
    {
        return x&(-x);
    }
    void add(ll x,ll y)
    {
        for(;x<=n;x+=lowbit(x)){
            tree1[x]=max(tree1[x],y);
            tree2[x]=min(tree2[x],y);
        }
    }
    ll getmax(ll x,ll y){
        if(y>x){
            if(y-lowbit(y)>x) return max(tree1[y],getmax(x,y-lowbit(y)));
            else return max(a[y],getmax(x,y-1));
         }
        return a[x];
    }
    ll getmin(ll x,ll y)
    {
        if(y>x){
            if(y-lowbit(y)>x) return min(tree2[y],getmin(x,y-lowbit(y)));
            else return min(a[y],getmin(x,y-1));
        }
        return a[x];
    }
    start{
        /**for(int i=1;i<=3;i++) num[i]=read;
        sort(num+1,num+4);
        ll ans=num[1]*num[2]/2;
        cout<<ans;
        n=read,m=read;
        s[0]=0;
        for(int i=1;i<=n;i++)
        {
            s[i]=read;
            s[i]+=s[i-1];
        }
        int left=0,right=0;
        ll res=INT_MIN;
        for(int i=1;i<=n;i++)
        {
            if(i-a[left]>m) left++;
            res=max(res,s[i]-s[a[left]]);
            while(left<=right&&s[a[right]]>=s[i]) right--;
            a[++right]=i;
        }
        cout<<res;**/
        n=read,m=read;
        memset(tree2,0x3f3f3f3f,sizeof(tree2));
        for(int i=1;i<=n;i++)
        {
            a[i]=read;
            add(i,a[i]);
            ///tree2[i]=inf;///在这里赋值就是不行必须要在程序开始进行赋值
        }
    ///memset(tree2,0x3f3f3f3f,sizeof(tree2));放在这里也是不行的过不了
    ///0x3f3f3f3f是最大值
        for(int i=1;i<=m;i++)
        {
            int l=read,r=read;
            printf("%lld
    ",getmax(l,r)-getmin(l,r));
        }
    	end;
    }
    
    

    /////##################################################################
    我喜欢称这个小函数为玄学函数

    ll lowbit(ll x)
    {
        return x&(-x);
    }
    

    建一棵树

    void add(ll x,ll y)
    {
        for(;x<=n;x+=lowbit(x)){///用while可能会舒服点
            tree1[x]=max(tree1[x],y);
            tree2[x]=min(tree2[x],y);
        }
    }
    

    找区间最大

    ll getmax(ll x,ll y){
        if(y>x){
            if(y-lowbit(y)>x) return max(tree1[y],getmax(x,y-lowbit(y)));
            else return max(a[y],getmax(x,y-1));
         }
        return a[x];
    }
    

    找区间最小,这里注意将数组tree2的每个元素赋值为最大以便找最小值

    ll getmin(ll x,ll y)
    {
        if(y>x){
            if(y-lowbit(y)>x) return min(tree2[y],getmin(x,y-lowbit(y)));
            else return min(a[y],getmin(x,y-1));
        }
        return a[x];
    }
    
  • 相关阅读:
    poj 3617 Best Cow Line
    POJ 1852 Ants
    Pairs
    codility MinAbsSum
    Codeforces Beta Round #67 (Div. 2)C. Modified GCD
    timus 1018. Binary Apple Tree
    C
    HDU 1299Diophantus of Alexandria
    BZOJ2155(?) R集合 (卡特兰数)
    CSP模拟赛 number (二分+数位DP)
  • 原文地址:https://www.cnblogs.com/PushyTao/p/13144214.html
Copyright © 2011-2022 走看看