2 5 5 4 3 2 1 5 5 1 2 3 4
Case #1: 4 Case #2: 1HintIn the second sample, we choose “5” so that after the first round, sequence becomes “1 2 3 4 5”, and the algorithm completes.
区域赛居然还会出这么水的题==
说题意:正常的逆序数做法是从头到尾遍历一遍,累加在此数之前出现的比这个数值大的数的个数,可能还要用到离散化,比方说这个题:(本题没必要离散化 都是1-n之间的数)
具体实现呢:我们之前求逆序数的方法是累加在某个数之前出现比他大的数,而这个题显然要反过来求,我们就反向遍历,若存在先出现的比这个数小的情况,sum++即可,注意,求和的时候遇到大于0就return!否则超时
/************ hdu5122 2016.3.21 1856MS 38092K 1928 B C++ *************/ #include <iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxn 1000005 struct node { int id,val; }num[maxn]; bool cmp(node n1,node n2) { return n1.val<n2.val; } struct Tree { int l,r,tot; }tree[maxn<<2]; int rnk[maxn]; void build(int rt,int l,int r) { tree[rt].l=l;tree[rt].r=r; tree[rt].tot=0; if(l==r)return; int mid=(l+r)/2; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); } void update(int rt,int x) { tree[rt].tot++; if(tree[rt].l==tree[rt].r&&tree[rt].l==x) return; int mid=(tree[rt].l+tree[rt].r)/2; if(x<=mid)update(rt<<1,x); else update(rt<<1|1,x); } int query(int rt,int l,int r) { int sum=0; if(tree[rt].l==l&&tree[rt].r==r) return tree[rt].tot; int mid=(tree[rt].l+tree[rt].r)/2; if(r<=mid) { sum=query(rt<<1,l,r); if(sum>0)return 1; } else if(l>mid) { sum=query(rt<<1|1,l,r); if(sum>0)return 1; } else { sum=query(rt<<1,l,mid)+query(rt<<1|1,mid+1,r); if(sum>0)return 1; } return sum; } int change[maxn]; int main() { 、、 freopen("cin.txt","r",stdin); int t,n,cas=1; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&num[i].val); num[i].id=i; change[num[i].val]=i; } //sort(num,num+n,cmp); //for(int i=0;i<n;i++) rnk[num[i].id]=i+1; build(1,0,n+1); int sum=0,tmp=0; for(int i=n-1;i>=0;i--) { // int x = rnk[i]; tmp=query(1,0,num[i].val-1); // printf("i=%d,sum=%d\n",i,sum); if(tmp>0) sum++; update(1,num[i].val); } printf("Case #%d: %d\n",cas++,sum); } return 0; }