于是completely寄掉了|

yshpdyt

园龄:1年1个月粉丝:6关注:4

ABC343题解

前言:

E太毒瘤了,G先咕着。

A

题意

给定两个非负个位数 a+b,输出任意非负个位数 c 使得c neqa+b

Sol

相加为 0 输出 1,否则输出 0

Code

#include<bits/stdc++.h>
#define ll long long
#define N 200005
#define endl "\n" 
#define fi first
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
ll n,a[N];
string s;
int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    cin>>s;
    ll fl=0;
    if((s[0]>='A'&&s[0]<='Z'))fl=1;
     if(!fl){
            cout<<"No\n";
            return 0;
    }
    for(int i=1;i<s.size();i++){
        if(s[i]<='z'&&s[i]>='a')continue;
        cout<<"No\n";
        return 0;

    }
    cout<<"Yes\n";
    return 0;
}



B

题意

给定无向图的邻接矩阵(如果 ai,j=1,说明 i,j 直接相连),从小到大输出每个点直接相连的点。

Sol

ai,j=1 输出 j 即可。

Code

#include<bits/stdc++.h>
#define ll long long
#define N 200005
#define endl "\n" 
#define fi first
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
ll n,m;
int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            ll x;
            cin>>x;
            if(x)cout<<j<<" ";
        }
        cout<<endl;
    }
    return 0;
}

C

题意

找到最大的小于 n 的回文数,使得该数字是某个正整数的三次方。

Sol

直接枚举 i,判断 i3 是不是回文数即可。

Code

#include<bits/stdc++.h>
#define ll long long
#define N 200005
#define endl "\n" 
#define fi first
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
ll n,m;
string s;
ll a[N];
ll ans=1;
void check(ll n){
    ll p=n;
    ll cnt=0;
    while(n){
        a[++cnt]=n%10;
        n/=10;
    }
    for(int i=1,j=cnt;i<=j;i++,j--)if(a[i]!=a[j])return;
    ans=p;
    return ;
}
int main(){
    cin>>n;
    for(ll i=1;i;i++){
        if(i*i*i>n){
            cout<<ans<<endl;
            break;
        }
        check(i*i*i);
    }
    return 0;
}

D

题意

n 个人,T 个事件,第 i 个事件会让第 ai 个人的得分增加 bi,求每个事件后不同得分的人数。

Sol

开一个桶实时维护每个得分的人数,每次修改该得分人数的数量,如果人数减为 0 就答案减一,如果人数从 0 增加到 1 就答案加一。

这里用了 set,但其实用个变量维护就行。注意一开始全是 0

Code

#include<bits/stdc++.h>
#define ll long long
#define N 200005
#define endl "\n" 
#define fi first
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
ll n,m;
string s;
ll a[N],b[N],f[N];
map<ll,ll>mp;
set<ll>q;
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)mp[0]++;
    q.insert(0);
    for(int i=1;i<=m;i++){
        ll x,y;
        cin>>x>>y;
        mp[f[x]]--;
        if(mp[f[x]]==0)q.erase(f[x]);
        f[x]=f[x]+y;
        if(mp[f[x]]==0)q.insert(f[x]);
        mp[f[x]]++;
        cout<<q.size()<<endl;
    }
    return 0;
}

E

题意

本场最答辩和恶心的题。

空间直角坐标系有三个边长为 7的正方体,给定你三个体积:

v1 表示刚好一个正方体覆盖区域的体积和。
v2 表示刚好两个正方体覆盖区域的体积和。
v3 表示刚好三个正方体覆盖区域的体积和。

报告任意符合题意的三个正方体的坐标或输出无解,要求坐标绝对值在 100 以内,只需要输出 (x,y,z) 坐标都最小的端点。

Sol

答辩暴力,几何,容斥题,以下分成三个部分来讲。

先规定一下,一个长方体,我们设它 (x,y,z) 坐标都最小的端点坐标为 (sx,sy,sz),坐标都最大的为 (ex,ey,ez),这样用两个坐标就可以表示一个长方体:R=(sx,sy,sz)(ex,ey,ez)

暴力

由于是已知边长的正方体,所以只需要确定一个点就能确定所有点,直接枚举所有可能的端点坐标,复杂度是 O(2009),不用想肯定会超。

首先考虑一个问题,对于一个合法的答案,我们可以将三个正方体视为一个整体,保持他们之间的相对位置不变,将他们整体随意平移到坐标系的任意位置,对答案毫无影响。

那我们不妨让其中一个正方体的一个端点位于原点,设这个正方体为 A=(0,0,0)(7,7,7),其余两个为B,C。这样可以少枚举一个正方体,复杂度 O(2006),还是会超。

考虑其他两个正方体单独来说可能的位置,尽管他们仍然可能在空间中的任意位置,但对于本题来说,无非整体上就是两种:与 A 相交或不相交,相交的情况可能由于相交程度不一样有很多细微的不同,但是对于不相交的情况,我们将正方体放的离 A 远一些或者近一些都一样,都不会对答案产生影响。

考虑离 A 最近的情况,可以放的范围。显然最近的情况就是挨着,也就是边上的点部分重和,如下白色方框范围,红色是 A
img
然后如果和 A 相交,肯定也不会超过这个范围(7x,y,z14),那么我们可以枚举这个范围内的端点坐标,这样一定可以覆盖所有情况,也就是枚举 7sx,sy,sz7,ex=sx+7,ey=sy+7,ez=sz+7。总共要枚举两个正方体,复杂度是 O(146),大概是 7e6,剩下了充沛的时限,就不进一步优化了,(如果你想卡常,考虑空间图形各种翻转情况,B,C 位置互换之类的等效解)。

几何

这部分主要是用来计算长方体重叠体积的。

先从一维的线段开始,两条线段什么时候有重叠部分?重叠部分如何表示?显然是(有个 min 是要考虑相交或包含的关系):

lilj&& lj<rji

R=(li,min(rj,ri))

二维呢?分开考虑:

xlixlj&& xlj<xri

yliylj&& ylj<yri

R=(xli,yli)(min(xrj,xri),min(yrj,yri))

三维呢?仍然分开考虑:

xlixlj&& xlj<xri

yliylj&& ylj<yri

zlizlj&& zlj<zri

R=(xli,yli,zli)(min(xrj,xri),min(yrj,yri),min(zrj,zri))

这样子,我们得到了两个长方体重叠部分的端点坐标。

三个长方体重叠的部分呢?先求两个长方体的重叠部分坐标,然后看作一个新的长方体,再和另一个取重叠部分。

如果没有重叠部分,让所有坐标都为 0 即可。

长方体计算体积就很简单了,V=(sxex)×(syey)×(szez)

强烈建议把长方体封装进结构体。

容斥

简单三者容斥。

我们可以拿 NOI2024 举办学校的校徽举例。

规定一些名称:
AA=(0,0,0)(7,7,7) 的正方体。
BB=(sx1,sy1,sz1)(sx1+7,sy1+7,sz1+7) 的正方体。
CC=(sx2,sy2,sz2)(sx2+7,sy2+7,sz2+7) 的正方体。
ABAB 重叠部分的长方体。
BCBC 重叠部分的长方体。
ACAC 重叠部分的长方体。
ABCABC 重叠部分的长方体。
V(R):长方体 R 的体积。
v1 表示刚好一个正方体覆盖区域的体积和。
v2 表示刚好两个正方体覆盖区域的体积和。
v3 表示刚好三个正方体覆盖区域的体积和。
img

图上应该以及很清楚了,不难得到等式:

V(ABC)=V3

V(AB)+V(BC)+V(AC)3×V(ABC)=V2

V(A)+V(B)+V(C)2×(V(AB)+V(BC)+V(AC))+3×V(ABC)=V1

算出来判断就行。

花了两个半小时写的题解,求关注qwq。

Code

#include<bits/stdc++.h>
#define ll long long
#define y1 yy 
#define x1 xx 
#define z1 zz 
#define y2 yyy
#define x2 xxx
#define z2 zzz
#define y3 yyyy
#define x3 xxxx
#define z3 zzzz
#define N 200005
#define endl "\n" 
#define fi first
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
struct qwq{
    ll sx,sy,sz;
    ll ex,ey,ez;
    ll v(){return abs((ex-sx)*(ey-sy)*(ez-sz));}
}A,B,C;
qwq cd(qwq n1,qwq n2){
    ll sx=0,sy=0,sz=0;
    ll ex=0,ey=0,ez=0;
    if(!n1.v())return {sx,sy,sz,ex,ey,ez};
    if(!n2.v())return {sx,sy,sz,ex,ey,ez};
    if(n1.sx<=n2.sx&&n1.ex>=n2.sx)sx=n2.sx,ex=min(n1.ex,n2.ex);
    if(n2.sx<=n1.sx&&n2.ex>=n1.sx)sx=n1.sx,ex=min(n1.ex,n2.ex);
    if(n1.sy<=n2.sy&&n1.ey>=n2.sy)sy=n2.sy,ey=min(n1.ey,n2.ey);
    if(n2.sy<=n1.sy&&n2.ey>=n1.sy)sy=n1.sy,ey=min(n1.ey,n2.ey);
    if(n1.sz<=n2.sz&&n1.ez>=n2.sz)sz=n2.sz,ez=min(n1.ez,n2.ez);
    if(n2.sz<=n1.sz&&n2.ez>=n1.sz)sz=n1.sz,ez=min(n1.ez,n2.ez);
    return {sx,sy,sz,ex,ey,ez};
}
void sol(ll a,ll b,ll c){
    A={0,0,0,7,7,7};
    for(int x1=-7;x1<=7;x1++){
        for(int y1=-7;y1<=7;y1++){
            for(int z1=-7;z1<=7;z1++){
                B={x1,y1,z1,x1+7,y1+7,z1+7};
                qwq AB=cd(A,B);
                for(int x2=-7;x2<=7;x2++){
                    for(int y2=-7;y2<=7;y2++){
                        for(int z2=-7;z2<=7;z2++){
                            C={x2,y2,z2,x2+7,y2+7,z2+7};
                            qwq AC=cd(A,C);
                            qwq BC=cd(B,C);
                            qwq ABC=cd(AB,C);
                            if(ABC.v()!=c)continue;
                            if(AC.v()+AB.v()+BC.v()-3*c!=b)continue;
                            if(A.v()+B.v()+C.v()-2*b-3*c!=a)continue;
                            cout<<"Yes\n";
                            cout<<A.sx<<" "<<A.sy<<" "<<A.sz<<" ";
                            cout<<B.sx<<" "<<B.sy<<" "<<B.sz<<" ";
                            cout<<C.sx<<" "<<C.sy<<" "<<C.sz<<" \n";
                            return ;
                        }
                    }
                }
            }
        }
    }
    cout<<"No\n";
}
ll a,b,c;
int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    cin>>a>>b>>c;
    sol(a,b,c);
    return 0;
}


F

题意

维护一个序列,支持单点修改,区间查询次大值出现次数。

Sol

经典特色线段树板题。

维护区间的最大值,次大值,最大值出现次数,次大值出现次数即可。

这样做是显然的,一个区间的最大值显然是两个子区间的最大值较大的那一个,一个区间的次大值,是两个子区间最大值较小的那一个,或者次大值最大的那一个,分类讨论一下即可。

Code

#include<bits/stdc++.h>
#define ll long long
#define N 800005
#define endl "\n" 
#define fi first
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
ll a[N],n;
namespace tr{
    #define mid ((l+r)>>1)
    #define ls (p<<1)
    #define rs (p<<1|1)
    //最大值,次大值,最大值出现次数,次大值出现次数。
    struct qwq{
        ll mx,my,nx,ny;
        friend qwq operator+(const qwq &a,const qwq &b){
            qwq c={0,0,0,0};
            if(a.mx>b.mx){
                c.mx=a.mx;
                c.nx=a.nx;
                if(b.mx>a.my){
                    c.my=b.mx;
                    c.ny=b.nx;
                }
                if(b.mx==a.my){
                    c.my=b.mx;
                    c.ny=b.nx+a.ny;
                }
                if(b.mx<a.my){
                    c.my=a.my;
                    c.ny=a.ny;
                }
                return c;
            }
            if(a.mx==b.mx){
                c.mx=a.mx;
                c.nx=a.nx+b.nx;
                if(b.my>a.my){
                    c.my=b.my;
                    c.ny=b.ny;
                }
                if(b.my==a.my){
                    c.my=b.my;
                    c.ny=b.ny+a.ny;
                }
                if(b.my<a.my){
                    c.my=a.my;
                    c.ny=a.ny;
                }
                return c;
            }
            if(a.mx<b.mx){
                c.mx=b.mx;
                c.nx=b.nx;
                if(b.my>a.mx){
                    c.my=b.my;
                    c.ny=b.ny;
                }
                if(b.my==a.mx){
                    c.my=b.my;
                    c.ny=b.ny+a.nx;
                }
                if(b.my<a.mx){
                    c.my=a.mx;
                    c.ny=a.nx;
                }
                return c;
            }
        }
    }tr[N];
    void build(ll p,ll l,ll r){
        if(l==r){
            tr[p].mx=a[l];
            tr[p].my=0;
            tr[p].nx=1;
            tr[p].ny=0;
            return ;
        }
        build(ls,l,mid);
        build(rs,mid+1,r);
        tr[p]=tr[ls]+tr[rs];
    }
    void upd(ll p,ll l,ll r,ll x,ll t){
        if(l==r){
            tr[p].mx=t;
            tr[p].my=0;
            tr[p].nx=1;
            tr[p].ny=0;
            return ;
        }
        if(x<=mid)upd(ls,l,mid,x,t);
        if(x>mid)upd(rs,mid+1,r,x,t);
        tr[p]=tr[ls]+tr[rs];
    }
    qwq qr(ll p,ll l,ll r,ll le,ll ri){
        if(le<=l&&ri>=r)return tr[p];
        if(le<=mid&&ri>mid)return qr(ls,l,mid,le,ri)+qr(rs,mid+1,r,le,ri);
        if(le<=mid)return qr(ls,l,mid,le,ri);
        if(ri>mid)return qr(rs,mid+1,r,le,ri);
        return {0,0,0,0};
    }
}
ll m=0;
int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    tr::build(1,1,n);
    while(m--){
        ll op,x,y;
        cin>>op>>x>>y;
        if(op==1){
            tr::upd(1,1,n,x,y);
        }else cout<<tr::qr(1,1,n,x,y).ny<<endl;
    }
    return 0;
}

G

题意

Sol

Code


本文作者:yshpdyt

本文链接:https://www.cnblogs.com/yshpdyt/p/18049508

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   yshpdyt  阅读(74)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起