C. Berland Regional

题目
思路
我们很容易想到要枚举每一个分组,从1~n,然后用vector存下每一个组里面的数,从大到小的存,然后求一下每一组的前缀和,如果就这样开始写的话,复杂度还是o(n^2)的,对于2e5的数据来说还是会超时的。
我们可以进行一个小优化,我们对每组的人数进行排序,人数从小到大的排序,如果当前的分组大于某些组的时候可以直接跳过这些组,以后分组越来越大,所以剩下的组数也会越来越少,这样的复杂度是o(n*sqrt(n))复杂度是可以过这一题的。
代码

#include 
#define ll long long
#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define fi first
#define se second
#define pb push_back
#define me memset
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
vector<ll>v[N];
struct Node
{
     
    int id,val;
}a[N];
bool cmp(Node x,Node y)
{
     
    if(x.id==y.id) return x.val>y.val;
    return x.id<y.id;
}
struct C
{
     
    int num,idx;
}c[N];
bool cmp1(C x,C y)
{
     
    return x.num<y.num;
}
int main()
{
     
    FAST;
    int t;
    cin>>t;
    while(t--)
    {
     
        int n;
        cin>>n;
        for(int i=1 ; i<=n ; i++)
        {
     
            a[i]={
     0,0};
            c[i]={
     0,0};
            v[i].clear();
        }
        for(int i=1 ; i<=n ; i++) cin>>a[i].id;
        for(int i=1 ; i<=n ; i++) cin>>a[i].val;
        sort(a+1,a+1+n,cmp);
        for(int i=1 ; i<=n ; i++) v[a[i].id].push_back(a[i].val);
        for(int i=1 ; i<=n ; i++)
        {
     
            int size=v[i].size();
            c[i].num=size;
            c[i].idx=i;
            for(int j=1 ; j<size ; j++)
            {
     
                v[i][j]+=v[i][j-1];  //处理出来每一组的前缀和。
            }
        }
        sort(c+1,c+1+n,cmp1);
       // for(int i=1 ; i<=n ; i++) cout<
        int p=1;
        ll ans=0;
        for(int i=1 ; i<=n ; i++)
        {
     
            ans=0;
            while(c[p].num<i)
            {
     
                p++;
               // cout<
            }
            for(int j=p ; j<=n ; j++)
            {
     
                int vi=c[j].idx;
                int size=c[j].num;
                int cnt=size-size%i;
               // cout<
                ans+=v[vi][cnt-1];
            }
            cout<<ans<<" ";
        }
        cout<<endl;
    }
    return 0;
}

总结
这一题没有想到对每一组的人数排序,然后根据人数的多少来枚举,这样随着分组的增大,是有连续性的。

你可能感兴趣的:(C. Berland Regional)