Loading

UVA11300 Spreading the Wealth 思维题

链接

这个题主要的难点在于模型建构。

这是一道均分纸牌带环,复制一段变为链,考虑用二维前缀和,但是因为绝对值难以处理。

怎么办?

我们考虑用代数方法去做这个题。

\(x_i\)\(i+1\)\(i\) 的钱是多少。注意 \(x_i\) 可以是负的,如果为负,这代表着 \(i\)\(i+1\) 一些钱。

\(M\) 为最终每个人剩下的钱数。

那么有:

\[\begin{cases} M=a_1+x_n-x_1\\ M=a_2+x_1-x_2\\ ...\\ M=a_n+x_{n-1}-x_n \end{cases} \]

不难发现,把第 \(2\) 个方程到第 \(n\) 个方程全部加起来能够得到第一个方程。所以第一个方程没有用,我们关注剩下的方程。

不难发现答案就是:

\[\min\{\sum\limits_{i=1}^{n}|x_i| \} \]

\(x_i,2\le i\le n\) 可以通过上面的方程组用 \(x_1\) 来表示,由此我们得到:

\[x_2=a_2+x_1-M\\ x_3=a_3+x_2-M=a_2+a_3-2\times M+x_1\\ ... \]

\(x_1\) 前面的那一部分我们用前缀和来维护。

于是这个题就变成了求:

\[\sum\limits_{i=1}^n|x_1-c_1| \]

的最小值。不难发现这就是中位数。

代码:

#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define uint unsigned int
#define ull unsigned long long
#define N 10010
#define M number
using namespace std;

const int INF=0x3f3f3f3f;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

struct Ants{
    int posi,id;
    char chao;
    inline bool operator < (const Ants &b)const{
        return posi<b.posi;
    }
};
Ants a[N],b[N],ans[N];

int t,l,times,n;

inline char GetChar(){
    char c=getchar();
    while(c!='L'&&c!='R') c=getchar();
    return c;
}

int main(){
    freopen("my.in","r",stdin);
    freopen("my.out","w",stdout);
    read(t);
    for(int q=1;q<=t;q++){
        read(l);read(times);read(n);
        for(int i=1;i<=n;i++){
            read(a[i].posi);a[i].id=i;
            a[i].chao=GetChar();
            b[i]=a[i];
            if(a[i].chao=='L') a[i].posi-=times;
            else a[i].posi+=times;
        }
        sort(a+1,a+n+1);
        sort(b+1,b+n+1);
        a[0].posi=-INF;a[n+1].posi=INF;
        for(int i=1;i<=n;i++){
            if(a[i].posi<0||a[i].posi>l) a[i].chao='F';
            else if(a[i].posi==a[i-1].posi||a[i].posi==a[i+1].posi) a[i].chao='T';
        }
        for(int i=1;i<=n;i++){
            ans[b[i].id]=a[i];
        }
        printf("Case #%d:\n",q);
        for(int i=1;i<=n;i++){
            if(ans[i].chao=='F') printf("Fell off");
            else if(ans[i].chao=='T') printf("%d Turning",ans[i].posi);
            else printf("%d %c",ans[i].posi,ans[i].chao);
            putchar('\n'); 
        }
        printf("\n");
    }
    return 0;
}
posted @ 2021-07-12 19:18  hyl天梦  阅读(32)  评论(0编辑  收藏  举报