NEERC Southern Subregional 2012

NEERC Southern Subregional 2012

Problem B. Chess Championship

题目描述:有两个序列\(a, b\),两个序列都有\(n\)个数,并且这\(2n\)个数两两不同,现在要将这两个序列里的数两两配对,组成\(n\)个数对,要求数对中\(a\)的数比\(b\)的数大的数对个数要比其它的多\(m\)个。问方案数。

solution

将这\(2n\)个数从小到大排,预处理出前\(i\)个数中\(a, b\)的个数\(suma, sumb\), \(f[i][j][k]\)表示前\(i\)个数,匹配了\(j\)对\(a>b\)的数对,还有\(k\)个\(a\)未匹配。

如果第\(i\)个数是\(a\)的数:

  1. 与前面的一个还没有匹配的\(b\)匹配,\(f[i+1][j+1][k]+=f[i][j][k]*(sumb[i-1]-suma[i-1]+k)\)
  2. 留着让后面的\(b\)匹配,\(f[i+1][j][k+1]+=f[i][j][k]\)

    如果第\(i\)个数是\(b\)的数:

  3. 与前面一个还没有匹配的\(a\)匹配,\(f[i+1][j][k-1]+=f[i][j][k]*k\)
  4. 留着让后面的\(a\)匹配,\(f[i+1][j][k]+=f[i][j][k]\)

答案就是\(f[2*n+1][0][0]\),因为空间不够,所有要有滚动数组,而且卡常,所以要控制好枚举的范围。

时间复杂度:\(O(n^3)\)

Problem E. Dragons and Princesses

题目描述:有\(n\)个格子,每个格子上有一条龙或一个公主,每条龙守着一定数量的金币,现在要从第一个格子出发,遇到龙时可以选择跳过,也可以选择杀死龙并拿走金币,如果遇到公主,假如杀龙的数量大于等于公主的要求,那么就要娶这个公主,已知最后一个格子是一个公主,并且娶且只娶最后一个公主,问最多能拿多少金币,输出方案。

solution

首先从后往前,算出到达每个格子时最多能杀多少条龙,然后用一个堆维护最大的那几条龙即可。

时间复杂度:\(O(nlogn)\)

Problem F. Dumbbells

题目描述:有\(n\)个球,每个球的重量为\(w_i\),价值为\(c_i\),现在要取尽量多的集合,每个集合必须要有\(k\)个球,并且\(k\)个球的重量不同,而且每个集合的重量集合必须相同。问在最多能构成多少个集合,并且最大价值为多少。

solution

统计每种重量的球有多少,从大到小排序,然后取前\(k\)种重量,对应的集合数为第\(k\)中重量的球的个数\(s\),然后算出球数大于等于\(s\)的重量中每种重量的最贵的\(s\)个球的总价值,然后取价值最大的\(k\)中重量。

时间复杂度:\(O(nlogn)\)

Problem G. Database optimization

题目描述:有\(n\)个物品,每个物品有不超过\(4\)种性质,有\(m\)个询问,每次询问拥有某些性质的物品有多少。

solution

性质的集合不超过\(n*2^4\)种,预处理出这些集合各有多少个物品拥有即可,用一个\(map\)就好了。

时间复杂度:\(O(2^4n+m)\)

Problem H. Sultan‘s Pearls

题目描述:有一串珠子放在桌上,一共有\(n\)个珠子,其中有\(m\)个悬在桌边,每个珠子有重量和价值,现在一次可以从两边取一个珠子(桌上或悬挂),如果取的是悬挂的珠子,则要从桌上移一个珠子使悬挂的珠子总数不变,当悬挂的珠子的总重量大于桌上的珠子的总重量乘\(k\)时,珠子会掉下来,问在保证珠子不掉下来的情况下,能拿走的最大总价值,输出方案。

solution

方案显然是先拿走悬挂的,然后再拿在桌上的。所以可以枚举最终悬挂的珠子的最下面一个是哪个,然后二分出桌面上最多能拿走多少个珠子,然后贪心地拿就好。

时间复杂度:\(O(nlogn)\)

Problem J. Ternary Password

题目描述:有一个只有\(0, 1, 2\)的字符串,现在可以修改某些位置的字符,使得最终有\(a\)个\(0\),\(b\)个\(1\),问最少需要修改多少个字符,并且输出修改后的字符串。

solution

贪心。

时间复杂度:\(O(n)\)

Problem K. Tree Queries Online

题目描述:给定一棵树,树有边权,不断地删掉一条边,输出删掉的边的权值\(val\),取出分开的两棵树中点数较少的树(如果相同则取最小编号的点所在的树),这棵树的边权乘\(val\),另一棵树的边权加\(val\)。强制在线。

solution

启发式拆树,拆的时候同时扩展两棵树,有一棵树搜完就停下,然后把这棵树的边权暴力更新,新建一个集合存这些点,旧的集合存另外一棵树,在旧集合打上边权增量标记。

时间复杂度:\(O(nlogn)\)

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int mod=99990001;
const int maxn=int(2e5)+100;

struct LINK
{
    int id, pre, next;
};

int n, now;
int h[maxn], nx[maxn];
LINK t[maxn*2];
int block[maxn];
int blockcnt;
LL ans[maxn], mark[maxn];
queue<int> q[2];
int edge[2][maxn];
bool vis[maxn];

void join(int u, int v)
{
    t[now].id=v; t[now].next=h[u]; t[now].pre=-1; if (h[u]!=-1) t[h[u]].pre=now; h[u]=now++;
    t[now].id=u; t[now].next=h[v]; t[now].pre=-1; if (h[v]!=-1) t[h[v]].pre=now; h[v]=now++;
}
void read()
{
    scanf("%d", &n);
    for (int i=1; i<=n; ++i) h[i]=-1;
    for (int i=1; i<n; ++i)
    {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        join(u, v);
        ans[i]=w;
    }
}
void bfs(int u, int v, int blockidx, LL w)
{
    int minidx[2]={u, v};
    edge[0][0]=edge[1][0]=0;
    nx[u]=h[u]; nx[v]=h[v];

    while (!q[0].empty()) q[0].pop();
    while (!q[1].empty()) q[1].pop();
    q[0].push(u); q[1].push(v);

    while (!q[0].empty() && !q[1].empty())
    {
        for (int j=0; j<2; ++j)
        {
            int cur=q[j].front();
            bool flag=false;

            for (int i=nx[cur]; i>-1; i=nx[cur]=t[i].next)
                if (!vis[i/2+1])
                {
                    flag=true;
                    minidx[j]=min(minidx[j], t[i].id);
                    q[j].push(t[i].id);
                    edge[j][++edge[j][0]]=i/2+1;
                    nx[t[i].id]=h[t[i].id];
                    vis[i/2+1]=true;
                    nx[cur]=t[i].next;
                    break;
                }
            if (!flag) q[j].pop();
        }
    }

    int idx=0;
    if ((!q[0].empty() && q[1].empty()) || (q[0].empty() && q[1].empty() && minidx[1]<minidx[0])) idx=1;

    ++blockcnt;
    for (int i=1; i<=edge[idx][0]; ++i)
    {
        ans[edge[idx][i]]=(ans[edge[idx][i]]+mark[blockidx])*w%mod;
        block[edge[idx][i]]=blockcnt;
    }
    mark[blockidx]=(mark[blockidx]+w)%mod;

    for (int j=0; j<2; ++j)
        for (int i=1; i<=edge[j][0]; ++i) vis[edge[j][i]]=false;
}
void edge_del(int idx)
{
    for (int cur=idx*2-2; cur<idx*2; ++cur)
    {
        if (t[cur].pre!=-1) t[t[cur].pre].next=t[cur].next;
        else h[t[cur^1].id]=t[cur].next;
        if (t[cur].next!=-1) t[t[cur].next].pre=t[cur].pre;
    }
}
void solve()
{
    blockcnt=1;
    for (int i=1; i<n; ++i) block[i]=1;

    for (int i=1; i<n; ++i)
    {
        int idx;
        scanf("%d", &idx);
        printf("%lld\n", (ans[idx]=(ans[idx]+mark[block[idx]])%mod));
        fflush(stdout);
        edge_del(idx);
        bfs(t[(idx-1)*2].id, t[idx*2-1].id, block[idx], ans[idx]);
    }
}
int main()
{
    read();
    solve();
    return 0;
}

Problem L. Preparing Problem

solution

仔细算一下就好了。

时间复杂度:\(O(1)\)

原文地址:https://www.cnblogs.com/GerynOhenz/p/9919818.html

时间: 2024-10-21 09:50:42

NEERC Southern Subregional 2012的相关文章

2018-2019 ICPC, NEERC, Southern Subregional Contest

目录 2018-2019 ICPC, NEERC, Southern Subregional Contest (Codeforces 1070) A.Find a Number(BFS) C.Cloud Computing(线段树) D.Garbage Disposal(模拟) E.Getting Deals Done(二分) F.Debate(贪心) H.BerOS File Suggestion(后缀自动机) I.Privatization of Roads in Berland(网络流)

模拟赛小结:2014-2015 ACM-ICPC, NEERC, Southern Subregional Contest

2014-2015 ACM-ICPC, NEERC, Southern Subregional Contest 2019年10月11日 15:30-20:30(Solved 6,Penalty 740) 国庆咸鱼十来天,回来又过了快一个星期,终于和队友约上了模拟赛.(周三拖周四,因为队(fei)友(zhai)们要跑1000米,又拖到周五QAQ) I:00:04.开场翻翻题目,机智如我很快找到一个贪心. D:00:36.看了看现场榜,有人交D.F和M,lh同学已经开F去了,xk同学说他M思路差不多

D. Dog Show 2017-2018 ACM-ICPC, NEERC, Southern Subregional Contest, qualification stage (Online Mirror, ACM-ICPC Rules, Teams Preferred)

http://codeforces.com/contest/847/problem/D 巧妙的贪心 仔细琢磨... 像凸包里的处理 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <time.h> 6 #include <string> 7 #include <set> 8 #includ

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror) 体验记

原文链接https://www.cnblogs.com/zhouzhendong/p/CF1070.html 比赛网址:http://codeforces.com/contest/1070 感受 本来只打算玩玩的. 结果玩的海星. 我做 A 题的时候可能比较浮躁吧,各种傻错误,爆了 7 个罚时. 我 A 还没过,cly 神仙已经把 CDK 切光了. 4点半过一会儿,各自回家.cly 要剃头,就咕咕咕了.我本来也要剃的,后来临时决定先打题. 然后过了 A ,顺手切掉了 H 和 F ,开了 E ,猜

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror) Partial Solution

从这里开始 题目列表 瞎扯 Problem A Find a Number Problem B Berkomnadzor Problem C Cloud Computing Problem D Garbage Disposal Problem E Getting Deals Done Problem F Debate Problem G Monsters and Potions Problem H BerOS File Suggestion Problem I Privatization of

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)

http://codeforces.com/contest/1070 A 给你一个d和s,求一个最小的数,使的能整除d,并且每位数的和为s. 如果确定了某n位数取模d的值,那么再计算同样的n位数,取模d也是相同的值时,就多此一举了.比如10%2 == 0  20%2 == 0  同样是两位数,取模2都是等于0.所以取最小的就可以了. 1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const

2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred) Solution

A. Find a Number Solved By 2017212212083 题意:$找一个最小的n使得n % d == 0 并且 n 的每一位数字加起来之和为s$ 思路: 定义一个二元组$<d, s>$ 表示当前状态模d的值,以及每一位加起来的值 跑最短路,从$<0, 0>  跑到 <0, s>$ 1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 1e5 +

2013-2014 ACM-ICPC, NEERC, Eastern Subregional Contest PART (7/10)

\[2013-2014\ ACM-ICPC,\ NEERC,\ Eastern\ Subregional\ Contest\] \(A.Podracing\) \(B.The\ battle\ near\ the\ swamp\) 签到 //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<bits/stdc++.h> using namespace std; function<void(

ACM ICPC 2011–2012, NEERC, Northern Subregional Contest J. John’s Inversions(合并排序求逆序数对数)

题目链接:http://codeforces.com/gym/100609/attachments 题目大意:有n张牌,每张牌有红色和蓝色两面,两面分别写了一些数字,同种颜色的任意两个数字若排在前面的数字比排在后面的数字大就叫做一对逆序数.求怎样排序得到的逆序数对最少. 解题思路:其中一种颜色的数字是顺序且这种颜色数字相同时对应的另一种颜色的数字是顺序时得到的逆序数对数最少.难点在于求逆序数对数.因为数量很大O(n^2)复杂度不能满足,这里根据合并排序的原理求解每个数字前面有多少个比它大的数字,