首页 > ACM题库 > HDU-杭电 > HDU 3743-Frosh Week -树状数组-[解题报告]HOJ
2015
02-22

HDU 3743-Frosh Week -树状数组-[解题报告]HOJ

Frosh Week

问题描述 :

During Frosh Week, students play various fun games to get to know each other and compete against other teams. In one such game, all the frosh on a team stand in a line, and are then asked to arrange themselves according to some criterion, such as their height, their birth date, or their student number. This rearrangement of the line must be accomplished only by successively swapping pairs of consecutive students. The team that finishes fastest wins. Thus, in order to win, you would like to minimize the number of swaps required.

输入:

The first line of input contains one positive integer n, the number of students on the team, which will be no more than one million. The following n lines each contain one integer, the student number of each student on the team. No student number will appear more than once.

输出:

The first line of input contains one positive integer n, the number of students on the team, which will be no more than one million. The following n lines each contain one integer, the student number of each student on the team. No student number will appear more than once.

样例输入:

3
3
1
2

样例输出:

2

思路:我们只需坚守一个原则,本来就在左边的坚决不把它换到右边。也就是相邻的两个数,左边小,右边大,那么就不调换。这样对每个数,只要统计左边比它大的数的个数。可以从后面开始用树状数组统计比它小的数的个数是一样的。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define Maxn 1000010
#define lowbit(x) (x&(-x))
using namespace std;
int C[Maxn],num[Maxn],n,r[Maxn];
void init()
{
    memset(C,0,sizeof(C));
}
int cmp(int a,int b)
{
    return num[a]<num[b];
}
int Sum(int pos)
{
    int sum=0;
    while(pos>0)
    {
        sum+=C[pos];
        pos-=lowbit(pos);
    }
    return sum;
}
void update(int pos)
{
    while(pos<=n)
    {
        C[pos]++;
        pos+=lowbit(pos);
    }
}
int main()
{
    int i,j;
    while(scanf("%d",&n)!=EOF)
    {
        init();
        for(i=1;i<=n;i++)
             scanf("%d",num+i);
        for(i=1;i<=n;i++)
            r[i]=i;
        sort(r+1,r+n+1,cmp);
        int cnt=0;
        int temp=num[r[1]];
        num[r[1]]=++cnt;
        for(i=2;i<=n;i++)
        {
            if(num[r[i]]!=temp) temp=num[r[i]],num[r[i]]=++cnt;
            else num[r[i]]=temp;
        }
        __int64 ans=0;
        for(i=n;i>=1;i--)
        {
            ans+=(__int64)Sum(num[i]);
            update(num[i]);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

 

参考:http://www.cnblogs.com/wangfang20/archive/2013/07/30/3226495.html


  1. #include <cstdio>
    #include <cstring>

    const int MAXSIZE=256;
    //char store[MAXSIZE];
    char str1[MAXSIZE];
    /*
    void init(char *store) {
    int i;
    store['A']=’V', store['B']=’W',store['C']=’X',store['D']=’Y',store['E']=’Z';
    for(i=’F';i<=’Z';++i) store =i-5;
    }
    */
    int main() {
    //freopen("input.txt","r",stdin);
    //init(store);
    char *p;
    while(fgets(str1,MAXSIZE,stdin) && strcmp(str1,"STARTn")==0) {
    if(p=fgets(str1,MAXSIZE,stdin)) {
    for(;*p;++p) {
    //*p=store[*p]
    if(*p<’A’ || *p>’Z') continue;
    if(*p>’E') *p=*p-5;
    else *p=*p+21;
    }
    printf("%s",str1);
    }
    fgets(str1,MAXSIZE,stdin);
    }
    return 0;
    }

  2. 为什么for循环找到的i一定是素数叻,而且约数定理说的是n=p1^a1*p2^a2*p3^a3*…*pk^ak,而你每次取余都用的是原来的m,也就是n

  3. #include <cstdio>
    #include <cstring>

    const int MAXSIZE=256;
    //char store[MAXSIZE];
    char str1[MAXSIZE];
    /*
    void init(char *store) {
    int i;
    store['A']=’V', store['B']=’W',store['C']=’X',store['D']=’Y',store['E']=’Z';
    for(i=’F';i<=’Z';++i) store =i-5;
    }
    */
    int main() {
    //freopen("input.txt","r",stdin);
    //init(store);
    char *p;
    while(fgets(str1,MAXSIZE,stdin) && strcmp(str1,"STARTn")==0) {
    if(p=fgets(str1,MAXSIZE,stdin)) {
    for(;*p;++p) {
    //*p=store[*p]
    if(*p<’A’ || *p>’Z') continue;
    if(*p>’E') *p=*p-5;
    else *p=*p+21;
    }
    printf("%s",str1);
    }
    fgets(str1,MAXSIZE,stdin);
    }
    return 0;
    }