首页 > 其他分享 >20220924--CSP-S模拟10

20220924--CSP-S模拟10

时间:2022-09-24 21:56:50浏览次数:59  
标签:10 ch 20220924 -- sum long int WR include

A. 欧几里得的噩梦

首先发现第一问所询问的异或值数量就是所求的第二问的最小集合的元素个数次方
因为除去集合里的任一一个元素,其中若干个元素异或之后的集合就不可能为原来的集合(否则不满足最小条件)
然后对线性基的插入过程进行一个模拟
\(\cdots\cdots\) 扑街是肯定的
注意到

给定的集合的二进制表示下最多只有两位为 1。

考虑并查集,假如只有 \(x\) 位为 \(1\) ,那么就和虚点 \(m+1\) 连边,否则给 \(x\) 和 \(y\) 连边
容易发现此时并查集内所维护的其实就是目前的连通块中选若干个数能表示出的集合,当发现此时 x 和 y 已经联通,那么就不插入。由于要维护字典序最小,那么其实边读边插就可以了。

贺一下BE的
#include <set>
#include <cstdio>
#include <algorithm>
#define Reg register
#define ll long long
using namespace std;
const int maxn=500100,mod=1e9+7;
int n,m,tot,f[maxn];
int ans[maxn];
inline int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<1)+(s<<3)+(ch^48);
        ch=getchar();
    }
    return s*w;
}
inline ll qpow(ll A,ll B){
    ll Ass=1;
    while(B){
        if(B&1) Ass=A*Ass%mod;
        A=A*A%mod;
        B>>=1;
    }
    return Ass;
}
inline int finds(int x){
    if(x!=f[x]) f[x]=finds(f[x]);
    return f[x];
}
inline void Merge(int x,int y){
    x=finds(x),y=finds(y);
    f[y]=x;
}
int main(){
    n=read(),m=read();
    for(Reg int i=1;i<=m+1;++i) f[i]=i;
    for(Reg int i=1;i<=n;++i){
        int opt=read(),x=read();
        if(opt==1){
            if(finds(x)!=finds(m+1)){
                Merge(x,m+1);
                ans[++tot]=i;
            }
        }else{
            int y=read();
            if(finds(x)!=finds(y)){
                Merge(x,y);
                ans[++tot]=i;
            }
        }
    }
    printf("%lld %d\n",qpow(2,tot),tot);
    for(Reg int i=1;i<=tot;++i) printf("%d ",ans[i]);
    return 0;
}

B. 清扫

设某一颗子树中的根节点为 \(u\) ,子树权值和为 \(sum\) ,子树最大权值为 \(maxx\) ,那么稍微推导即可知以下三个合法条件:

\[\begin{cases} sum\geqslant a_u\\ sum\leqslant 2a_u\\ maxx\leqslant a_u \end{cases}\]

不满足其中之一即可输出无解,满足的话就需要再考虑 \(a_u\) 在子树删除完之后应该是什么。
设子树之间删除次数为 \(x\) ,子树之外删除次数为 \(y\) ,稍微推导即可知以下一个二元一次方程组:

\[\begin{cases} 2x+y=sum\\ x+y=a_u \end{cases}\]

所以能推出来 \(a_u=2a_u−sum\)
最后判断 $a_{root} 是否为 \(0\) 即可。
注意为避免漏掉叶节点,应选择度大于 \(1\) 的点作为根节点,但此时 \(n=2\) 的情况下需要一个小小的特判。

点击查看代码
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=1001000;
struct Edge{
    int pre,to;
}edge[WR<<1];
int head[WR],tot;
int n,rt;
int a[WR],dp[WR];
int ipt[WR];
bool leaf[WR],flag=true;
int read(){
	int s=0,w=1;
	char ch=getchar();
	while(ch>'9'||ch<'0'){
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=(s<<1)+(s<<3)+ch-'0';
		ch=getchar();
	}
	return s*w;
}
void add(int u,int v){
    edge[++tot].pre=head[u];
    edge[tot].to=v;
    head[u]=tot;
}
void dfs(int u,int root){
    for(int i=head[u];i;i=edge[i].pre){
        int v=edge[i].to;
        if(v==root) continue;
        dfs(v,u);
        if(!flag) return;
        if(dp[v]>a[u]){
            flag=false;
            return;
        }
        dp[u]-=dp[v];
        if(dp[u]<0){
            flag=false;
            return;
        }
    }
    if(dp[u]>a[u]||dp[u]<0){
        flag=false;
        return;
    }
}
signed main(){
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    if(n==2){
        if(a[1]==a[2]) printf("YES\n");
        else printf("NO\n");
        return 0;
    }
    for(int i=1;i<n;i++){
        int u=read(),v=read();
        add(u,v);add(v,u);
        ipt[u]++,ipt[v]++;
    }
    for(int i=1;i<=n;i++){
        if(ipt[i]==1) leaf[i]=true,dp[i]=a[i];
        else rt=i,dp[i]=a[i]*2;
    }
    dfs(rt,0);
    if(!flag||dp[rt]!=0) printf("NO\n");
    else printf("YES\n");
	return 0;
}

C. 购物

代码不超过 \(40\) 行
结论:将 \(a_i\) 从小到大排序之后,求出序列中的前缀和 \(sum_i\) ,若存在 \(\large\lceil \frac{a_i}{2} \rceil > sum_{i−1}\),那么 \([sum_{i−1},\lceil \frac{a_i}{2}\rceil ]\) 的范围内无贡献。
首先我们显然不能用大于 \(a_i\) 的数来找属于这一范围的价值和,那样只会比 \(\lceil \frac{a_i}{2}\rceil\) 更大,此时找小于 \(a_i\) 的数也只会比 \(\lceil \frac{a_i}{2}\rceil\) 更小——这段区间不会产生贡献
相应的,也能证明 \(\large sum_i>\lceil \frac{a_i}{2}\rceil\) 的情况下的答案区间一定是连续的
那么实现就比较显然了,先判断是否存在上述无贡献的区间,之后将区间拓展到 \(sum_i\) 即可

点击查看代码
#include<cstdio>
#include<cmath>
#include<algorithm>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=1001000;
int n;
int a[WR];
int sum;
int read(){
	int s=0,w=1;
	char ch=getchar();
	while(ch>'9'||ch<'0'){
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=(s<<1)+(s<<3)+ch-'0';
		ch=getchar();
	}
	return s*w;
}
signed main(){
    n=read();
    for(int i=1;i<=n;i++) a[i]=read(),sum+=a[i];
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++){
        int l=a[i-1],r=ceil(a[i]/2.0);
        if(l<r) sum-=r-l-1;
        a[i]+=a[i-1];
    }
    printf("%lld\n",sum);
	return 0;
}

D. ants

回滚莫队板子
然鹅我还不会回滚莫队
放个 \(50\) 分的跑路

点击查看代码
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<cmath>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=101000;
struct SegmentTree{
    int lson,rson;
    int l,r,len,val;
}tree[WR<<3];
struct Ask{
    int l,r,num;
}query[WR];
int n,m,l,r;
int a[WR],BL;
int cnt[WR],blng[WR];
int ans[WR];
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<3)+(s<<1)+ch-48;
        ch=getchar();
    }
    return s*w;
}
void pushup(int k){
    tree[k].l=tree[k<<1].l;
    tree[k].r=tree[k<<1|1].r;
    if(tree[k<<1].l==tree[k<<1].len) tree[k].l+=tree[k<<1|1].l;
    if(tree[k<<1|1].r==tree[k<<1|1].len) tree[k].r+=tree[k<<1].r;   
    tree[k].val=max(tree[k<<1].r+tree[k<<1|1].l,max(tree[k<<1].val,tree[k<<1|1].val));
}
void build(int k,int l,int r){
    tree[k].lson=l,tree[k].rson=r;
    if(l==r){
        tree[k].len=1;
        return;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    tree[k].len=tree[k<<1].len+tree[k<<1|1].len;
}
void modify(int k,int pos,int val){
    if(tree[k].lson==tree[k].rson){
        tree[k].l=val;
        tree[k].r=val;
        tree[k].val=val;
        return;
    }
    int mid=(tree[k].lson+tree[k].rson)>>1;
    if(pos<=mid) modify(k<<1,pos,val);
    else modify(k<<1|1,pos,val);
    pushup(k);
}
bool cmp(Ask x,Ask y){
    if(blng[x.l]==blng[y.l]) return x.r<y.r;
    return blng[x.l]<blng[y.l];
}
signed main(){
    n=read(),m=read();
    BL=n/sqrt(m)+1;
    for(int i=1;i<=n;i++) a[i]=read(),blng[i]=(i-1)/BL+1;
    build(1,1,n);
    for(int i=1;i<=m;i++){
        query[i].l=read(),query[i].r=read();
        query[i].num=i;
    }
    sort(query+1,query+1+m,cmp);
    l=1,r=0;
    for(int i=1;i<=m;i++){
        while(l<query[i].l){cnt[a[l]]--;if(!cnt[a[l]]) modify(1,a[l],0);l++;}
        while(l>query[i].l){l--;cnt[a[l]]++;if(cnt[a[l]]==1) modify(1,a[l],1);}
        while(r<query[i].r){r++;cnt[a[r]]++;if(cnt[a[r]]==1) modify(1,a[r],1);}
        while(r>query[i].r){cnt[a[r]]--;if(!cnt[a[r]]) modify(1,a[r],0);r--;}
        ans[query[i].num]=tree[1].val;
    }
    for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
    return 0;
}

标签:10,ch,20220924,--,sum,long,int,WR,include
From: https://www.cnblogs.com/WintersRain/p/16726565.html

相关文章

  • 基于SSM的驾校预约系统的设计与实现Java驾校管理系统(源码调试+讲解+文档)
    ......
  • 深度学习:计算机视觉
    1、图像增广图像增广(imageaugmentation)技术通过对训练图像做一系列随机改变,来产生相似但又不同的训练样本,从而扩大训练数据集的规模。图像增广的另一种解释是,随机改变训......
  • 【闲散漫步】水题日记
    \(\textrm{luoguP1306斐波那契公约数}\)斐波那契结论题:\[\gcd(F_n,F_m)=F_{\gcd(n,m)}\]\(\textrm{luoguP1445[Violet]樱花}\)简单的计数。\(\textrm{luoguP21......
  • 关于tkinter中lambda函数使用的注意事项与陷阱分析
    背景:今天笔者使用tkinter开发了一个小的gui工具,分别基于列表的方式创建存储了一堆的文本框与复制按钮想的是复制按钮一一对应文本框,因为有着这样的规律,文本框与复制按钮的......
  • java五周目笔记
    数组—、数组的概述1.数组的理解:数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。2.数组相关的概念:......
  • 约瑟夫环相关问题
    与力扣 圆圈中最后剩下的数字类似:https://leetcode.cn/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/将环加入数组中,每次计算index=(index+m-1)%......
  • WiFi知识点
    WiFi名字的由来  Wi-Fi这个术语经常被误以为是指无线保真(WirelessFidelity),类似历史悠久的音频设备分类:长期高保真(1930年开始采用)或Hi-Fi(1950年开始采用)。即便是Wi-F......
  • LeeCode 动态规划(四)
    LeeCode动态规划(四)LeeCode198:打家劫舍题目描述你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连......
  • mysql将字符串类型字段后面的小数点和零去掉
    背景现有student表,表中的学生年龄student_age字段中的值,是通过读取excel中的信息后更新到数据库中,但是因为处理不当,导致年龄的均带有.0,如28.0实际上应该是28。我们需要将......
  • SCI论文写作指南
    目录科技论文的特点时态的使用论文的逻辑结构作者选择期刊写作Title/论文题名题名题名的作用题名基本要求作者作者姓名的拼音表达方式作者单位名与地址的标署摘要的写作与......