楼兰图腾 题解
Posted yzx1798106406
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了楼兰图腾 题解相关的知识,希望对你有一定的参考价值。
楼兰图腾
【题目描述】
在完成了分配任务之后,西部 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; }
以上是关于楼兰图腾 题解的主要内容,如果未能解决你的问题,请参考以下文章