【纪中集训】2019.08.13【省选组】模拟3

T1

Description

  • 给出一个\(N*N(N≤600)\)的非负矩阵\(B=(b_{ij})\),和一个\(1*N\)的非负矩阵\(C=(c_{ij})\)。\(A=(a_{ij})\)是一个\(1*N\)的\(01\)矩阵,令矩阵\(D=(d_{ij}) (A*B-C)*A^T\),则\(D\)是一个\(1*1\)的矩阵。要求构造\(A\)矩阵最大化\(D\)矩阵的元素值,输出得到的\(D\)矩阵。

    Solution

  • 化下式子就知道答案为:\(\sum_{i=1}^n A_i[(\sum_{j=1}^n A_jB_{ij})-C_i]\)。
  • 这样的话,可以想象有一张\(N\)个点的完全图,第\(i\)个点的点权为\(C_i\),边\(<i,j>\)的权为\(B_{ij}\)。那问题就转化为在这张图上找一个子图,使得子图内边权和减点权和最大。
  • 可以yy成一种神奇的二元关系,然后转化为最小割模型。这里提供一种建图:对于点\(i\),我们从源点\(S\)向它连一条容量为\(\sum_{j=1}^n B_{ij}\)的边,从它向汇点\(T\)连一条容量为\(C_i\)的边;然后对于一个点对\(i≠j\),从\(i\)向\(j\)连一条容量为\(B_{ij}\)的边。这样用\(\sum B\)减去最小割即为答案。
  • 上述建图法的正确性是比较显然的。我们假设一开始全选,\(ans=\sum B\);然后考虑选点\(i\)的代价是\(C_i\)(即让\(ans-=C_i\)),不选点\(i\)的代价是\(\sum_{j可不选} B_{ij}+\sum_{j必选}B_{ji}\)。显然这种代价和即为答案。实际上,我们只要建出一个满足这些代价的图即可(因而有无数种建图方法)。

    Code

#include <cstdio>
#include <algorithm>
#define min(x,y) (x<y?x:y)
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;

const int N=666,M=2*N*N,inf=0x7fffffff;
int n,S,T,x,oub[N],la[N],ans,cur[N],dis[N],GAP[N];
struct edge{int v,l,ne;}e[M];

void link(int x,int y,int z)
{
    static int tot=1;
    e[++tot]=(edge){y,z,la[x]}, la[x]=tot;
    e[++tot]=(edge){x,0,la[y]}, la[y]=tot;
}

int flow(int x,int res)
{
    if(x==T) return res;
    int i,have=0;
    for(i=cur[x]; i; i=e[i].ne)
        if(e[i].l&&dis[x]==dis[e[i].v]+1)
        {
            cur[x]=i;
            int now=flow(e[i].v,min(res-have,e[i].l));
            e[i].l-=now, e[i^1].l+=now;
            if((have+=now)==res) return have;
        }
    cur[x]=la[x];
    if(!--GAP[dis[x]]) dis[S]=T+1;
    GAP[++dis[x]]++;
    return have;
}

int main()
{
    scanf("%d",&n), T=n+1;
    fo(i,1,n) fo(j,1,n)
    {
        scanf("%d",&x), oub[i]+=x, ans+=x;
        if(i^j) link(i,j,x);
    }
    fo(i,1,n) link(S,i,oub[i]), scanf("%d",&x), link(i,T,x);
    GAP[0]=T+1;
    while(dis[S]<=T) ans-=flow(S,inf);
    printf("%d",ans);
}

T2

Description

  • 一个平面直角坐标系上,有\(N(≤7000)\)个点,标号为1到N,其中第i个点的坐标为(x[i], y[i])。   
  • 求满足以下两个条件的点列{p[i]}的数目(假设{p[i]}的长度为M):   
    1) 对任意1 <= i < j <= M,必有y[p[i]] > y[p[j]];   
    2) 对任意3 <= i <= M,必有x[p[i-1]] < x[p[i]] < x[p[i-2]]或者x[p[i-2]] < x[p[i]] < x[p[i-1]]。   
  • 求满足条件的非空序列{p[i]}的数目,结果对一个整数\(Q(\in[1,1000000000])\)取模。

    Solution

  • 一道灵光一闪后就是普及难度的题目。
  • 可以先将点按x坐标排序,然后DP。设f[i][0/1]表示考虑到第i个点,它的下一个点在它左边/右边的答案。那我们可以从小到大枚举i,再从i-1到1枚举一个j,比较y[i]和y[j],若y[i]<y[j]则用f[i][0]转移f[j][1],否则用f[j][1]转移f[i][0]。
  • 画个图就很明了了。由于我们一定是从y小的转移向y大的,所以是没有后效性的;而且由于我们按x坐标排了序,在用一个f转移前,已经考虑完了中间的(比如用f[i][0]转移f[j][1],我们已经考虑完了所有j<j‘<i的f[j‘][1]对f[i][0]的贡献了),因而也是正确的。
  • 时间复杂度\(O(n^2)\)。

    Code

#include <cstdio>
#include <algorithm>
#define P(x,y) (x+=y)%=Q
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

const int N=7010;
int n,Q,f[N][2],ans;
struct dot{int x,y;}p[N];

bool cmp(const dot&a,const dot&b) {return a.x<b.x;}

int main()
{
    scanf("%d%d",&n,&Q);
    fo(i,1,n) scanf("%d%d",&p[i].x,&p[i].y);
    sort(p+1,p+n+1,cmp);
    fo(i,1,n)
    {
        f[i][0]=f[i][1]=1;
        fd(j,i-1,1) p[j].y>p[i].y ? P(f[j][1],f[i][0]) : P(f[i][0],f[j][1]);
    }
    fo(i,1,n) P(ans,f[i][0]), P(ans,f[i][1]);
    printf("%d",(ans-n+Q)%Q);
}

T3

Description

  • 给出一棵\(N(≤100000)\)个带权点的有根树,每个点的孩子是从左到右有序的。一棵树的价值为所有叶节点的权值和减去每对相邻叶节点的路径上(不含那两个叶节点)的最大点权值。剪枝的本质是将某些结点的子树全部删去,使自己作为新的叶结点。
  • 对树进行一些剪枝,使树的价值最大。剪枝的方式为:如果一个结点的孩子都是叶结点,就可以将它所有的孩子剪去。

    Solution

  • 也是一道水题。。。没切真是耻辱
  • 记lc(x)为从x出发,沿最左节点走下去形成的链,称为左链;rc(x)为右链。那每次肯定是有一对相邻的兄弟节点u、v,用一个rc(u)的答案更新lc(v)的答案。(当然反过来也可以,因为把整棵树左右翻转后的答案是不变的)
  • 暴力转移即可,因为一个点至多只会在一条左链和一条右链上,因此是\(O(n)\)的。
  • 转移时用一个单调队列优化一下。

    Code

#include <cstdio>
#define max(x,y) (x>y?x:y)
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

const int N=11e4,inf=0x3f3f3f3f;
int n,w[N],t,p,pa[N],tot,to[N],ne[N],la[N],ls[N],rs[N],f[N],top,h[N],m[N],h1[N],h2[N],ans;

void work(int x,int y)
{
    h1[0]=-inf;
    for(top=0; x; x=rs[x])
    {
        h[++top]=x;
        m[top+1]=max(m[top],w[x]);
        h1[top]=max(h1[top-1],f[x]);
        h2[top]=f[x]-m[top];
    }
    h2[top+1]=-inf;
    fd(i,top,1) if(h2[i]<h2[i+1]) h2[i]=h2[i+1];
    for(int k=0,d=m[1]; y; y=ls[y])
    {
        while(k<top&&d>m[k+1]) k++;
        f[y]=w[y]+max(h1[k]-d,h2[k+1]);
        if(d<w[y]) d=w[y];
    }
}

void dfs(int x,bool l,bool r)
{
    int ly=0;
    for(int i=la[x],y; y=to[i]; ly=y,i=ne[i])
    {
        if(ly) m[1]=w[x],work(ly,y);
        dfs(y,l&&!ly,r&&rs[x]==y);
    }
    if(l&&f[x]<w[x]) f[x]=w[x];
    if(r&&f[x]>ans) ans=f[x];
}

int main()
{
    scanf("%d",&n);
    fo(i,1,n)
    {
        scanf("%d%d",&w[i],&t);
        fo(j,1,t)
        {
            scanf("%d",&p);
            to[++tot]=p, ne[tot]=la[i], la[pa[p]=i]=tot;
            if(j==1) rs[i]=p;
            if(j==t) ls[i]=p;
        }
        f[i]=-inf;
    }
    dfs(1,1,1);
    printf("%d",ans);
}

原文地址:https://www.cnblogs.com/Iking123/p/11347964.html

时间: 2024-08-30 15:34:40

【纪中集训】2019.08.13【省选组】模拟3的相关文章

【纪中集训2019.08.20】【JZOJ6310】Global warming

题目链接 题意: 给出一个长度为$n$的序列$\{a_n\}$. 已知一个正整数$x$,你有一次机会指定区间$[l,r]$,令$\forall i\in [l,r],\;a_i=a_i+d\,(|d|\le x)$. 求最大化的最长上升子序列的长度. $1 \le n \le 2 \times 10^5 , \quad 1 \le a_i,x \le 10^9$且均为正整数. 分析: 可以很容易发现三个性质: 性质一:抬升$[l,r]$不优于抬升$[l,n]$,降低$[l,r]$不优于降低$[1

【纪中集训2019.08.21】【JZOJ6315】数字

题目链接 题意: 设$s(i)$为将$1\sim i$看做字符串后依次连接形成的串.给定正整数$n$,求最小的$i$使得$n$是$s(i)$的字串.$T$组数据. $n\le 10^{17}, \; t\le 10^4$ 分析: 不能模拟$s(i)$的组成过程来找答案,时间不能承受. 也不能预处理$s(k)$,空间不能承受. 那就只能在$n$上找答案. 以下把数字当成字面量来讨论,更方便. 同时,这里讨论的前缀和后缀不包括本身. 思考一下,答案分为三种: 1.$ans=n$ 2.$n$由$ans

纪中集训2019.11.08

A.三角形计数 题目链接 题意: 咕 分析: 咕 实现: 咕 小结: 咕 B.Isaac 题目链接 题意: 咕 分析: 咕 实现: 咕 小结: 咕 C.字符消除 题目链接 题意: 咕 分析: 咕 实现: 咕 小结: 咕 当天总结: 咕 原文地址:https://www.cnblogs.com/Hansue/p/11826709.html

【纪中集训2019.3.12】Mas的仙人掌

题意: ? 给出一棵\(n\)个点的树,需要加\(m\)条边,每条边脱落的概率为\(p_{i}\) ,求加入的边在最后形成图中仅在一个简单环上的边数的期望: 题解: 考虑每一条边的贡献是\((1-p_{i})*\Pi_{j}p_{j}(j!=i)\),这里\(j\)和\(i\)不能同时加入: 一条加入的边可以看成一条树上路径 ,即求所有和路径\(i\)相交的路径\(j\)的\(p_{j}\)的乘积: 将一条树上的链\((u,v)\)拆成两条\((u,lca)\)和\((v,lca)\); 这样会

【纪中集训2019.3.29】整除分块

题目 描述 ? 本题的背景是整除分块: ? 定义一个数列$a_{n,i} ? = ?\lfloor \frac{n}{i} \rfloor $ ; ? 求$\sum_{i=l}^{r} mex(a_n) $ ; ? 其中\(mex\)表示序列中最小的没有出现过的自然数: ? 答案对\(998244353\)取模 : 范围 ? \(1 \le T \le 65536 \ , \ 1 \le l ,r \le 10^{36}\) : ? 评测系统支持使用 $ _ _ int218 $ ,但是不能直接

【纪中集训2019.3.20】河

题目 描述 给出\(n\)条河流,每条河流是形式为\(k_{i}x+b_{i}\)的一次函数且只有\(x\)轴正半轴的部分: 河流的污染部分和另外一条河流的干净部分交汇,干净的部分会被污染: 有若干个工厂要建在\(b_{i}\)处,问有多少种方案使得所有的河流在无穷远处被污染: 答案对\(1e9+7\)取模 范围 $1 \le N \le 5 \times 10^5 ? ?, ??|k_{i}|,|b_{i}| \le 10^9 $ 保证\(b_{i}\)互不相同: 题解 需要先找到可以被一条河

纪中集训2019.11.06

A.困难的图论 题目链接 题意: 给出由$n$个点和$m$条边构成的无向连通图,要求选出一些边.一条边被选中当且仅当它恰好被一个简单环经过. 一个环被称为简单环,当且仅当这个环上的所有点都只在这个环中被经过了一次. 输出这些边的编号的异或和.边从$1$开始编号. $1\le n\le 10^6,\;1\le m\le min\{10^6,n\times (n+1) /2\}$. 分析: 注意:一个图可能有很多简单环,题目要求选中所有简单环上的边.考场上我就是这一点搞错了.(其实搞对了也很可能做不

纪中集训2019.11.07

A.极好的问题 题目链接 题意: 咕 分析: 咕 实现: 咕 小结: 咕 B.背包问题 题目链接 题意: 咕 分析: 咕 实现: 咕 小结: 咕 C.子树问题 题目链接 题意: 咕 分析: 咕 小结: 咕 当天总结: 咕 原文地址:https://www.cnblogs.com/Hansue/p/11811824.html

纪中集训2019.11.09

A.搞笑的代码 题目链接 题意: 咕 分析: 咕 实现: 咕 小结: 咕 B.道路维护 题目链接 题意: 咕 分析: 咕 实现: 咕 小结: 咕 C.字符串查询 题目链接 题意: 咕 分析: 咕 实现: 咕 小结: 咕 当天总结: 咕 原文地址:https://www.cnblogs.com/Hansue/p/11826647.html

木兮的纪中集训感想

嗯 第一次写博客... 就记录一下我这个OI萌新在纪中集训的感受吧 ## 学校 对于纪中,我这几天下来还是非常认可这所学校的:全国最美中学名不虚传(宿舍除外),校园环境非常好,虽然建校将近百年,但维护工作做得非常到位,看不出太多时间的痕迹. 训练 抛开学校环境不讲,这里的教学也是非常棒的,我来这里之前一直觉得集训应该是一件非常累的事,但事实并没有我想象的那么坏.先放一个训练的时间表 8:00 ~ 11:20 打模拟 14:00 ~ 17:30 讲题+自己改程序 19:00 ~ 21:50 自习