zoukankan      html  css  js  c++  java
  • 楼兰图腾 题解

    楼兰图腾

    【题目描述】

    在完成了分配任务之后,西部 314 来到了楼兰古城的西部。相传很久以前这片土地上(比楼
    兰古城还早)生活着两个部落,一个部落崇拜尖刀(‘ V’ ),一个部落崇拜铁锹(‘∧’ ),
    他们分别用 V 和∧的形状来代表各自部落的图腾。
    西部 314 在楼兰古城的下面发现了一幅巨大的壁画,壁画上被标记出了 n 个点,经测量发
    现这 N 个点的水平位置和竖直位置是两两不同的。西部 314 认为这幅壁画所包含的信息与
    这 N 个点的相对位置有关,因此不妨设坐标分别为(1,y1),(2,y2),...,(n,yn)其中 y1..yn
    是 1 到 n 的一个排列。
    西部 314 打算研究这幅壁画中包含着多少个图腾, 其中 V 图腾的定义如下(注意:图腾的
    形式只和这三个纵坐标的相对大小排列顺序有关) 1≤i<j<k≤n 且 yi>yj,yj<yk;而崇拜∧
    的部落的图腾被定义为 1≤i<j<k≤n 且 yi<yj,yj>yk;
    西部 314 想知道,这 n 个点中两个部落图腾的数目。因此,你需要编写一个程序来求出 V
    的个数和∧的个数。

    Input Data

    第一行一个数 n
    第二行是 n 个数,分别代表 y1,y2,...,yn

    Output Data

    两个数,中间用空格隔开,依次为 V 的个数和∧的个数。

    Input

    5
    1 5 3 2 4

    Output

    3 4

    Data Limit

    10%的数据 n≤600
    40%的数据 n≤5000
    100%的数据 n≤200000

    思路

    首先,10分思路就是直接暴力,直接枚举i,j,k。这里就不再说明了。

    再进一步,对于40%的数据,可以n^2的暴力,使用结构体,按照数值排序一遍,然后再枚举j点,最后从1~j-1枚举i,寻找a[i].id>a[j].id sum1++;寻找a[i].id<a[j].id sum2++,每回合,将ans加上sum之积就好了。

    有人会问?k呢?

    就是sum2啊

    i呢?

    就是sum1啊

    再运用组合,所以ans+=sum1*sum2。

    100分思路:

    考虑优化掉i的循环。将其转换成logn级别的算法。那么可以想到使用stl的set。但是本人太弱,打不来set。所以就直接上平衡树的模板,寻找一下该点在treap中的排名。

    代码如下:

    #include<algorithm>
    #include<bitset>
    #include<complex>
    #include<deque>
    #include<exception>
    #include<fstream>
    #include<functional>
    #include<iomanip>
    #include<ios>
    #include<iosfwd>
    #include<iostream>
    #include<istream>
    #include<iterator>
    #include<limits>
    #include<list>
    #include<locale>
    #include<map>
    #include<memory>
    #include<new>
    #include<numeric>
    #include<ostream>
    #include<queue>
    #include<set>
    #include<sstream>
    #include<stack>
    #include<stdexcept>
    #include<streambuf>
    #include<string>
    #include<typeinfo>
    #include<utility>
    #include<valarray>
    #include<vector>
    #include<cstring>
    #include<cmath>
    #define ll long long 
    #define eps 1e-4
    using namespace std;
    //priority_queue<int,vector<int>,greater<int> > q1;
    //priority_queue<int> q2;
    //std::set<int> s;
    //list<int> l;
    //map<int> mp;
    //queue<int> q;
    inline ll read(){
        ll ret=0,f=1;char ch=getchar();
        while (ch<'0'||ch>'9') {if (ch=='-') f=-f;ch=getchar();}
        while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
        return ret*f;
    }
    inline void write(ll zx){
        if(zx<0){zx=-zx;putchar('-');}
        if(zx<10) putchar(zx+'0');
        else{
            write(zx/10);
            putchar(zx%10+'0');
        }
    }
    
    struct data{
        ll lc,rc,key,pri,cnt,sze;
        #define lc(x) t[x].lc
        #define rc(x) t[x].rc
        #define v(x) t[x].key
        #define p(x) t[x].pri
        #define c(x) t[x].cnt
        #define s(x) t[x].sze
    }t[500010];
    ll n,rt;
    ll f[500010],ans1,ans2,pool;
    struct node{
        ll num,id;
    }a[500010];
    inline void upt(const ll &k){s(k)=s(lc(k))+s(rc(k))+c(k);}
    inline void Zig(ll &k){
        ll y=lc(k);
        lc(k)=rc(y);
        rc(y)=k;
        s(y)=s(k);
        upt(k);
        k=y;
    }
    inline void Zag(ll &k){
        ll y=rc(k);
        rc(k)=lc(y);
        lc(y)=k;
        s(y)=s(k);
        upt(k);
        k=y;
    }
    inline void Insert(ll &k,const ll &key){
        if(!k){
            k=++pool;v(k)=key;p(k)=rand();
            c(k)=s(k)=1;lc(k)=rc(k)=0;
            return ;
        }
        else ++s(k);
        if(v(k)==key) ++c(k);
        else if(key<v(k)){
            Insert(lc(k),key);
            if(p(lc(k))<p(k)) Zig(k);
        }else{
            Insert(rc(k),key);
            if(p(rc(k))<p(k)) Zag(k);
        }
        return ;
    }
    inline ll QueryRank(const ll &key){
        ll x=rt,res=0;
        while(x){
            if(key==v(x)) return res+s(lc(x))+1;
            if(key<v(x)) x=lc(x);
            else res+=s(lc(x))+c(x),x=rc(x);
        }
    }
    inline void Delete(ll &k,const ll &key){
        if(v(k)==key){
            if(c(k)>1) --c(k),--s(k);
            else if(!lc(k)||(!rc(k))) k=lc(k)+rc(k);
            else if(p(lc(k))<p(rc(k))) Zig(k),Delete(k,key);
            else Zag(k),Delete(k,key);
            return ;
        }
        --s(k);
        if(key<v(k)) Delete(lc(k),key);
        else Delete(rc(k),key);
        return ;
    }//平衡树模板
    bool cmp(node qx,node qy){
        return qx.num<qy.num;
    }
    bool cmp2(node qx,node qy){
        return qx.num>qy.num;
    }
    int main(){
        freopen("E.in","r",stdin);
        freopen("E.out","w",stdout);
        n=read();
        for(ll i=1;i<=n;i++) a[i].id=i,a[i].num=read();
        sort(a+1,a+n+1,cmp);
        for(ll i=1;i<=n;i++){
    //        Insert(a[i].id);
        /*    s.insert(a[i].id);
            s.upper_bound(s.begin(),s.end(),a[i].id);
    *///一开始想使用set的,忘记了怎么打
    Insert(rt,a[i].id);
    ll f1=QueryRank(a[i].id);f1--;
    ll f2=i-f1-1;
    /*
    ll f1=0,f2=0;
    for(ll j=1;j<i;j++){
        if(a[j].id<a[i].id) f1++;
        if(a[j].id>a[i].id) f2++;
    }
    *///暴力写法
    ans2+=f1*f2;
        }
        for(ll i=1;i<=n;i++){
            Delete(rt,a[i].id);
        }//记得清除
        sort(a+1,a+n+1,cmp2);
        for(ll i=1;i<=n;i++){
    //        Insert(a[i].id);
    /*
            s.insert(a[i].id);
            s.upper_bound(s.begin(),s.end(),a[i].id);
    */
    Insert(rt,a[i].id);
    ll f1=QueryRank(a[i].id);f1--;
    ll f2=i-f1-1;
    ans1+=f1*f2;
        }
        write(ans1);putchar(' ');
        write(ans2);putchar('
    ');//输出
        return 0;
    }
  • 相关阅读:
    阻止表单重复提交的办法以及支付成功后页面后退重复提交的解决方案
    jsp页面的共用
    空间谱专题02:波束形成(Beamforming)
    空间谱专题01:信号模型
    空间谱专题00:综述
    BP神经网络
    fdatool的滤波器设计
    Testbench
    Cordic算法简介
    快速删除注释
  • 原文地址:https://www.cnblogs.com/yzx1798106406/p/9747153.html
Copyright © 2011-2022 走看看