小总结:
今天上午又轮到老姚出题了,老姚这次出题莫名多了一道数论(说好的不出数论呢???),还有就是一如既往的dp多,四道题里面有两道dp题目......
明天高三学长要高考了,祝愿他们能取得的一个好成绩吧(稍微带一下我呗~)
T1:精灵魔法
看到这一道题乍一看是没有什么思路的,但是详细一想,我们可以对编号进行离散化,记录一下一个人前面还有多少人编号比他大,之后以速度为基准进行排序,再数出一个点前面有多少人编号比他大,减一下就好了,原因是两个点的互换在一个点超过一个点和一个点被超过是等价的,我们只统计其中一种就可以了,这里统计的是一个点超过的点的个数,于是我们考虑从大到小枚举,把前面的点记录一下他比几个点大,之后轮到某个点之后看一下前面有几个点比他大,这样就可以统计答案了,这是什么,是区间修改,单点查询,于是选择用线段树进行维护,注意在对速度进行排序的时候要特别处理一下相等的情况,不然会100->70.
其实关于这道题的主流做法是单点修改,区间查询(和我正好相反),还可以用归并排序求逆序对,我都试着打了一下,这里就不放代码了,退一下老师的博客:https://www.cnblogs.com/hbhszxyb/p/13253975.html
1 #include<bits/stdc++.h> 2 #define int long long 3 #define debug printf("-debug-\n") 4 #define lson (t<<1) 5 #define rson (t<<1|1) 6 #define mid ((l+r)>>1) 7 using namespace std; 8 const int N=1e6+10; 9 struct Tree{ 10 int w,lazy,siz; 11 }tree[N]; 12 void pushup(int t){ 13 tree[t].w=tree[lson].w+tree[rson].w; 14 } 15 void build(int t,int l,int r){ 16 tree[t].siz=r-l+1; 17 if(l==r) return; 18 build(lson,l,mid);build(rson,mid+1,r); 19 pushup(t); 20 } 21 void pushdown(int t){ 22 tree[lson].w+=tree[t].lazy; 23 tree[lson].lazy+=tree[t].lazy; 24 tree[rson].w+=tree[t].lazy; 25 tree[rson].lazy+=tree[t].lazy; 26 tree[t].lazy=0; 27 } 28 void change(int t,int l,int r,int cl,int cr){ 29 if(cl<=l&&r<=cr){ 30 tree[t].w+=tree[t].siz; 31 tree[t].lazy++; 32 return; 33 } 34 pushdown(t); 35 if(cr<=mid) change(lson,l,mid,cl,cr); 36 else if(cl>mid) change(rson,mid+1,r,cl,cr); 37 else{ 38 change(lson,l,mid,cl,cr);change(rson,mid+1,r,cl,cr); 39 } 40 pushup(t); 41 } 42 int query(int t,int l,int r,int pos){ 43 if(l==r){ 44 return tree[t].w; 45 } 46 pushdown(t); 47 if(pos<=mid) return query(lson,l,mid,pos); 48 else return query(rson,mid+1,r,pos); 49 } 50 int ans=0,cnt=0; 51 struct Node{ 52 int num,v; 53 }a[N]; 54 bool cmp1(Node a,Node b){ 55 return a.num<b.num; 56 } 57 bool cmp2(Node a,Node b){ 58 if(a.v==b.v) return a.num<b.num; 59 return a.v<b.v; 60 } 61 signed main(){ 62 int n; 63 scanf("%lld",&n); 64 build(1,1,n); 65 for(int i=1;i<=n;++i){ 66 scanf("%lld",&a[i].num); 67 } 68 for(int i=1;i<=n;++i) scanf("%lld",&a[i].v); 69 sort(a+1,a+n+1,cmp1); 70 for(int i=1;i<=n;++i) a[i].num=++cnt;//离散化 71 sort(a+1,a+n+1,cmp2); 72 for(int i=n;i>=1;--i){ 73 int cnt1=n-a[i].num; 74 int cnt2=query(1,1,n,a[i].num); 75 if(cnt1-cnt2>0) ans+=cnt1-cnt2; 76 if(a[i].num>1) change(1,1,n,1,a[i].num-1); 77 } 78 printf("%lld\n",ans); 79 return 0; 80 }