首页 > 其他分享 >省选联考 2018 题解

省选联考 2018 题解

时间:2023-03-26 16:12:14浏览次数:38  
标签:11 省选 题解 sum int max include 联考 dp

感觉有的歌确实不适合中午刚起来脑袋晕晕乎乎的就去听。太舒缓或者太激烈都不太好。太舒缓容易让人想睡回去,比如我今天中午打了半个小时哈欠。太激烈的……想象一下中午如果放 VIS::CRACKED 会怎样。反正要我我会晕一下午。那我得好好思考一下什么东西能卡在这两个界之间。那我寻思着不如来点 Eurobeat。那我想想最近的 Eurobeat 的例子似乎就是 INTERNET OVERDOSE。那算了吧,重复就不太好了。

真想整活的话可以刚个 Virtual to Live 上去。翻看 maimai 中二 音击 的曲库似乎是个好的主意。

思考了一下我有好办法了。脑力。

算了我推俩歌吧。一个 World's end loneliness。一个 И00。

一双木棋 chess

我超上来就博弈论这么刺激吗。遂看题解。wc 诈骗题那没事了。

首先可以发现每个状态都是占满左上角一片的。然后爆搜一下发现状态数 \(184756\)。然后过了。

顺便学习了一下对抗搜索是个什么东西。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <unordered_map>
#include <cstring>
#define int long long
using namespace std;
const int p=11;
int n,m,a[11][11],b[11][11],now[11];
unordered_map<int,int>mp;
int dfs(int x){
    if(mp.find(x)!=mp.end())return mp[x];
    int ret=x;
    for(int i=n;i>=1;i--){
        now[i]=ret%p;ret/=p;
    }
    int num=0;
    for(int i=1;i<=n;i++)num+=now[i];
    if(num&1)ret=0x3f3f3f3f;
    else ret=-0x3f3f3f3f;
    for(int i=1;i<=n;i++){
        if((i==1||now[i-1]>now[i])&&now[i]<m){
            now[i]++;int hs=0;
            for(int j=1;j<=n;j++)hs=hs*p+now[j];
            if(num&1)ret=min(ret,dfs(hs)-b[i][now[i]]);
            else ret=max(ret,dfs(hs)+a[i][now[i]]);
            now[i]--;
        }
    }
    return mp[x]=ret;
}
signed main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)scanf("%lld",&a[i][j]);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)scanf("%lld",&b[i][j]);
    }
    int ret=0;
    for(int i=1;i<=n;i++)ret=ret*p+m;
    mp[ret]=0;
    dfs(0);
    printf("%lld\n",mp[0]);
    return 0;
}

IIIDX

久仰大名。

首先 \(d\) 互不相同的时候有一个显然的贪心。想了想似乎有重复的时候不是很显然。

又想了一会发现直接提前留下一块等到时候再填上就行了。从大到小排序,线段树二分一下,有相同的选最右边的。

又想了想不太知道如何应付多次。发现扫到一个点的时候把父亲的贡献去掉就行了。那我是 sb。

然后写挂 nan 次。好线段树没 pushdown,鉴定为人菜。场切的人不多大概是因为有的细节比较诡异。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <unordered_map>
#include <cstring>
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
int n,size[500010],fa[500010],d[500010],ans[500010],cnt[500010];
double k;
bool vis[500010];
struct node{
    int l,r,min,lz;
}tree[2000010];
void pushup(int rt){
    tree[rt].min=min(tree[lson].min,tree[rson].min);
}
void pushtag(int rt,int val){
    tree[rt].min+=val;tree[rt].lz+=val;
}
void pushdown(int rt){
    if(tree[rt].lz){
        pushtag(lson,tree[rt].lz);pushtag(rson,tree[rt].lz);
        tree[rt].lz=0;
    }
}
void build(int rt,int l,int r){
    tree[rt].l=l;tree[rt].r=r;
    if(l==r){
        tree[rt].min=l;return;
    }
    int mid=(l+r)>>1;
    build(lson,l,mid);build(rson,mid+1,r);
    pushup(rt);
}
void update(int rt,int l,int r,int val){
    if(l<=tree[rt].l&&tree[rt].r<=r){
        pushtag(rt,val);return;
    }
    pushdown(rt);
    int mid=(tree[rt].l+tree[rt].r)>>1;
    if(l<=mid)update(lson,l,r,val);
    if(mid<r)update(rson,l,r,val);
    pushup(rt);
}
int query(int rt,int k){
    if(tree[rt].l==tree[rt].r){
        return tree[rt].min>=k?tree[rt].l:tree[rt].l+1;
    }
    pushdown(rt);
    if(tree[rson].min>=k)return query(lson,k);
    else return query(rson,k);
}
bool cmp(int a,int b){
    return a>b;
}
int main(){
    scanf("%d%lf",&n,&k);
    for(int i=1;i<=n;i++)scanf("%d",&d[i]);
    sort(d+1,d+n+1,cmp);
    for(int i=n-1;i>=1;i--){
        if(d[i]==d[i+1])cnt[i]=cnt[i+1]+1;
    }
    for(int i=n;i>=1;i--){
        fa[i]=i/k;
        size[i]++;size[fa[i]]+=size[i];
    }
    build(1,1,n);vis[0]=true;
    for(int i=1;i<=n;i++){
        if(!vis[fa[i]]){
            update(1,ans[fa[i]],n,size[fa[i]]-1);
            vis[fa[i]]=true;
        }
        int pos=query(1,size[i]);
        pos+=cnt[pos];cnt[pos]++;pos-=cnt[pos]-1;ans[i]=pos;
        update(1,ans[i],n,-size[i]);
    }
    for(int i=1;i<=n;i++)printf("%d ",d[ans[i]]);
    return 0;
}

秘密袭击 coat

感觉好像把原来考试的一个排列题搬到树上。那个题 \(O(nk)\) 的。

然后发现是神题。算了毕竟是 D1T3。

首先套路拆分每个点的贡献。然后人傻了。然而发现这题应该拆每种权值的贡献。

\[\begin{aligned} &\sum_{T\subseteq S}Kth\max(T)\\ =&\sum_{i=1}^Wi\sum_{T\subseteq S}[Kth\max(T)=i]\\ =&\sum_{i=1}^W\sum_{T\subseteq S}[Kth\max(T)\ge i]\\ =&\sum_{i=1}^W\sum_{T\subseteq S}[cnt_i\ge k] \end{aligned} \]

\(cnt_i\) 是 \(i\) 在 \(T\) 中出现次数。

等会再说。

劈配

Yazid 题,但是不是很神秘。

看见这种吊东西一堆限制再加个小数据范围果断网络流。那发现第一问就是个二分图匹配,每次加一个人一档志愿的边跑二分图匹配就行了(一个优化是如果不能匹配就把边删掉,听说不删会 t)。

考虑第二问。这个可以二分一个排名然后把这个排名以前的和自己都连上再跑。这个好像跑不过去,专门给每个前缀存一个处理完这些前缀时候的图在这上边跑好像就行了。

没写。

林克卡特树

神奇 WQS 二分。《题目并不难。》

首先看上去长得就像 dp 所以考虑 dp。然后转化一下问题,割掉 \(k\) 条边剩下 \(k+1\) 个连通块,每个连通块走一遍直径。那么就是选出 \(k+1\) 条链使得和最大。

设 \(dp_{x,i}\) 为到 \(x\) 有 \(i\) 条链。考虑怎么合并,发现没法合并。那加一维,\(dp_{x,i,0/1/2}\) 为到 \(x\) 有 \(i\) 条链,\(x\) 度数为 \(0/1/2\) 的答案。这个就可以讨论两边度数粘起来:

  1. 方便讨论,每次更新 \(dp_{x,i,0}=\max(dp_{x,i,0},dp_{x,i-1,1},dp_{x,i,2})\)。
  2. \(x\) 度数为 \(0\):把子树的最优解合并一下,即 \(dp_{x,i,0}=\max(dp_{x,i,0},dp_{x,j,0}+dp_{v,i-j,0})\)。
  3. \(x\) 度数为 \(1\):从自己的链和儿子的链选一个,即 \(dp_{x,i,1}=\max(dp_{x,i,1},dp_{x,j,0}+dp_{v,i-j,1}+w_{x,v},dp_{x,j,1}+dp_{v,i-j,0})\)。
  4. \(x\) 度数为 \(2\):自己在一条链中间,或者把自己和儿子粘起来,即 \(dp_{x,i,2}=\max(dp_{x,i,2},dp_{x,j,1}+dp_{v,i-j-1,1}+w_{x,v},dp_{x,j,2}+dp_{v,i-j,0})\)

边界 \(dp_{x,0,0}=dp_{x,0,1}=dp_{x,0,2}=0\),其他 \(-\infty\)。这是 \(O(nk)\) 的做法。

正解?打表发现这个东西是个上凸的(或者猜测每次贪心选最大),那 WQS 二分一下就行了。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define int long long
using namespace std;
int n,K;
struct gra{
    int v,w,next;
}edge[600010];
int t,head[300010];
void add(int u,int v,int w){
    edge[++t].v=v;edge[t].w=w;edge[t].next=head[u];head[u]=t;
}
struct node{
    int x,y;
    bool operator<(const node&s)const{
        return x==s.x?y>s.y:x<s.x;
    }
    node operator+(const node&s)const{
        return{x+s.x,y+s.y};
    }
    node operator+(const int&s)const{
        return{x+s,y};
    }
    node sub(int s){
        return {x-s,y+1};
    }
}dp[300010][3];
void dfs(int x,int f,int mid){
    dp[x][2]=max(dp[x][2],{-mid,1});
    for(int i=head[x];i;i=edge[i].next){
        if(edge[i].v!=f){
            dfs(edge[i].v,x,mid);
            dp[x][2]=max(dp[x][2]+dp[edge[i].v][0],(dp[x][1]+dp[edge[i].v][1]+edge[i].w).sub(mid));
            dp[x][1]=max(dp[x][1]+dp[edge[i].v][0],dp[x][0]+dp[edge[i].v][1]+edge[i].w);
            dp[x][0]=dp[x][0]+dp[edge[i].v][0];
        }
    }
    dp[x][0]=max(dp[x][0],max(dp[x][1].sub(mid),dp[x][2]));
}
signed main(){
    scanf("%lld%lld",&n,&K);K++; 
    for(int i=1;i<n;i++){
        int u,v,w;scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w);add(v,u,w);
    }
    int l=-1e12,r=1e12;
    while(l<r){
        int mid=(l+r)>>1;
        memset(dp,0,sizeof(dp));
        dfs(1,0,mid);
        if(dp[1][0].y<=K)r=mid;
        else l=mid+1;
    }
    memset(dp,0,sizeof(dp));
    dfs(1,0,l);
    printf("%lld\n",dp[1][0].x+l*K);
    return 0;
}

制胡窜

纯恶心人的题。

线段树合并维护 endpos 然后大力分类讨论。过程繁而不难,略去(真的很恶心,真的不想写了)。

标签:11,省选,题解,sum,int,max,include,联考,dp
From: https://www.cnblogs.com/gtm1514/p/17258838.html

相关文章

  • AT_abc295_d 题解
    一、题目描述:给你一个由数字0~9组成的字符串,长度为N(1<=N<=500000)。求出满足1<=l<=r<=N且在l~r区间内所有数字都出现了偶数次的整数对l,r有多少对。......
  • ABC295 D题 题解
    题意简述给定一个长度不超过\(5\times10^5\)的,仅有数字构成的字符串,问存在多少段子串,使得子串内字符重新排序后,前半段与后半段相同?做法分析重组后前后两部分相同,其实也......
  • [ARC139D] Priority Queue 2 题解
    上个世纪做过这题,然后今天比赛(abc295)出了道弱化没做出来,被pty喷了一遍后爬来写个题解/kk首先这种期望/总和题都有个套路,就是通过另外一种角度来计算每个元素的贡献。对......
  • ABC295 A~C题解
    A-ProbablyEnglish共有\(n\)个单词,如果出现过and,not,that,the,you其中一个单词至少一次,输出\(Yes\),否则,输出\(No\)。(输入的单词均为小写)按题意模拟即可:#include<......
  • 电脑升级到Win11后,插入耳机不识别问题解决方案?
    1、在网上搜索Realtek高清音频管理器下载 2、可以选择第一个点击下载安装,重启电脑后即可修复 ......
  • 省选武汉联测 11/GDKOI 2023 提高组 D2
    我是sb。T1线段树update写挂挂成70。某种程度上提前看题确实没什么用,会的都会不会的还是不会。游戏签到题。我没签上到是不是可以走了。首先我们只关心每个点往外......
  • 中国石油大学(北京)第三届“骏码杯”程序设计竞赛题解
    中国石油大学(北京)第三届“骏码杯”程序设计竞赛题解感谢大家的参与,我是本次比赛所有$10$道题目的出题人,在接下来的题解中,所有C++与Python的标程均由我本人编写,因为我......
  • Codeforces Round 859 (Div. 4) 题解集
    目录CF1807APlusorMinusDescriptionSolutionCodeCF1807BGrabtheCandiesDescriptionSolutionCodeCF1807CFindandReplaceDescriptionSolutionCodeCF1807DOddQueri......
  • 【牛客小白月赛69】题解与分析A-F【蛋挞】【玩具】【开题顺序】【旅游】【等腰三角形(
    比赛传送门:https://ac.nowcoder.com/acm/contest/52441感觉整体难度有点偏大。......
  • 「Gym102759B」Cactus Competition 题解
    传送门「Gym102759B」CactusCompetition题目大意有一个\(n\timesm\)的网格图,一个长度为\(n\)的序列\(a\),和一个长度为\(m\)的序列\(b\)。网格图中,第\(i\)......