-TEST 19 for NOIP 。。。(105-300)

本文总结了一次NOIP竞赛的备战经历,包括Blash数集、序列操作和图的最小生成树三个题目,分享了解题思路及代码实现,并提出审题、多练模板等经验教训。

头更更更大

这个11月完就要去搞NOIP了。。。

11月10天也就3次测试。。。为保佑进省一我还是每次测试玩都写个总结。。


emmm。。。。。又是三题全炸。。。
第一题做过忘了,顺手摔了一个优先队列上去,85。后来发现两个队列就能解决。。
第二题桶排序,搞了一个半小时心态爆炸放弃了去搞T3,回来顺手乱打了个暴力,20。
第三题最小生成树,暴力跑,但是由于没有开long long爆零。。。否则30到手。。。

按理说205很轻松的。。。orz

下面面详细解答:

T1(85/100):Blash数集

problem

题意:一个数集,规定如果x在集合中,那么 2x+1,3x+1 也在集合中。现在给你初始值x,询问第n大的数是多少。
样例

  • 输入
    1 100
    28 5437

  • 输出
    418
    900585

solution

当时知道是原题但是就是想不起来了。。。orz然后甩了个优先队列上去。
正解是用两个数组分别存储2x+1的项与3x+1的项,然后去去重就完事了。

T2(20/100):序列操作

problem

题意:给你一个数列,接下来要进行m次操作,每次操作要求你把数组中的c个正整数-1,问你最多能进行几次操作。
样例

  • 输入
    3 5
    1 2 5
    1 2 3 2 1

  • 输出
    3

solution

正解是二分,然而因为元素最大值不过1e4所以桶排序貌似跑的也不慢。。这里讲桶排序的。
相当于每次操作暴力模拟,如果桶中的元素少于要找的数,就把整个桶排序中的元素向下移一层(先把下面那层处理了再移);如果不少那就把需要找的数向下移一层就行。
论代码风格的简洁性的重要性。。。稍微改了下就是100。。。

T3(0/100):图

problem

题意
一个无向图,其中A条边的权值为k+x(每条边的权值由定值k与全局变量v决定),B条边的权值为k-x,而且这A,B条边分别能使整个图联通。询问对于不同的v,这个图的最小生成树的边权和是多少。
样例

  • 输入 
    5 4 4 4
    1 3 2
    1 2 0
    3 5 5
    3 4 10
    5 4 7
    2 3 6
    1 2 1000
    3 4 1000
    0
    1
    2
    3

  • 输出
    14
    16
    18
    18

solution

30%随便乱搞,暴力Kruskal。
50%利用特殊数据,A边一定是最优的,直接按着A边建就行。
100%。。。还是自己去后面看DZY大佬的代码吧orz

感想

审题!!!多打暴力!!!沉住气!!!多练模板!!!

代码:

T1:

std.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

#define U_MAX 200
inline char *get_str(char *str)
{
    fgets(str,U_MAX,stdin);
    if(str[strlen(str)-1] == '\n')
        str[strlen(str)-1] = '\0';
    return str;
}

inline void write(int x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}

const int kkk=4000000;
int top1,que1[kkk];
int top2,que2[kkk];
int a,n,m;
int main()
{
    //freopen("blash.in","r",stdin);
    //freopen("blash.out","w",stdout);  
    while(~scanf("%d%d",&a,&n))
    {
        int cnt1=1,cnt2=1;
        if(n==1){cout<<a<<endl;continue;}
        que1[top1=1]=2*a+1;
        que2[top2=1]=3*a+1;
        n-=1;
        while(n--)
        {
            if(que1[cnt1]==que2[cnt2])
            {
                a=que1[cnt1];
                que1[cnt1]=0;cnt1++;
                que2[cnt2]=0;cnt2++;
            }
            else if(que1[cnt1]<que2[cnt2])
            {
                a=que1[cnt1];
                que1[cnt1]=0;cnt1++;
            }
            else if(que1[cnt1]>que2[cnt2])
            {
                a=que2[cnt2];
                que2[cnt2]=0;cnt2++;
            }
            que1[++top1]=2*a+1;que2[++top2]=3*a+1;
        }
        cout<<a<<endl;
    }
}

T2

std.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

inline void write(int x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}

const int kkk=10005;

int n,m,flag;
int h,s[kkk];
int sum[kkk];

int main()
{
    //freopen("sequence.in","r",stdin);
    //freopen("sequence.out","w",stdout);   
    n=read();   m=read();   flag=1;
    for(int i=1;i<=n;i++)h=read(),sum[h]++,sum[0]=max(sum[0],h);
    h=sum[0];
    for(int i=1;i<=m;i++)
    {
        n=read();
        int tot=0,pos=0;
        for(int j=h;j>=1;j--)
        {
            if(tot+sum[j]>=n)
                {pos=j+1;break;}
            tot+=sum[j];
        }
        if(pos==0){cout<<i-1;return 0;}

        int tmp=n-tot;
        sum[pos-1]-=tmp;
        sum[pos-2]+=tmp;

        for(int j=pos;j<=h;j++)
        {
            sum[j-1]+=sum[j];
            sum[j]=0;
        }
    }
    cout<<m<<endl;
}

T3

std_50%.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

#define U_MAX 200
inline char *get_str(char *str)
{
    fgets(str,U_MAX,stdin);
    if(str[strlen(str)-1] == '\n')
        str[strlen(str)-1] = '\0';
    return str;
}

inline void write(int x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}

const int kkk=100005;
struct node{
    int u,v,k,flag;
}side[4*kkk];

int fa[kkk];
inline int ga(int x){return ((fa[x]==x)?(x):(fa[x]=ga(fa[x])));}

int v;
bool compi(const node&a,const node&b){return (a.k+a.flag*v)<(b.k+b.flag*v);}
bool comp(const node&a,const node&b){return (a.k)<(b.k);}

int n,a,b,q,ans1,ans2,cnt1,cnt2;
ll get_ans1()
{
    ll ans=0;
    for(int i=1;i<=n;i++)fa[i]=i;
    sort(side+1,side+a+b+1,compi);
    for(int i=1;i<=a+b;i++)
    {
        int u=side[i].u;
        int g=side[i].v;
        if(ga(u)!=ga(g))
        {
            fa[ga(u)]=ga(g);
            ans+=1LL*(side[i].k+side[i].flag*v);
        }
    }
    return ans;
}   

int main()
{
    //freopen("mst.in","r",stdin);
    //freopen("mst.out","w",stdout);    
    n=read();a=read();b=read();q=read();int flag=0;
    for(int i=1;i<=a;i++)
    {
        side[i].u=read();
        side[i].v=read();       
        side[i].k=read();   
        side[i].flag=1;
        if(side[i].k>1e8)flag=1;
    }
    for(int i=1;i<=b;i++)
    {
        side[i+a].u=read();
        side[i+a].v=read();     
        side[i+a].k=read();
        side[i+a].flag=-1;  
        if(side[i+a].k<9*1e8||side[i+a].k>1e9)flag=1;       
    }   
    if(flag)
    for(int i=1;i<=q;i++)
    {
        v=read();
        cout<<get_ans1()<<endl;
    }
    else
    {
        int numy=0;
        ll ans=0;
        for(int i=1;i<=n;i++)fa[i]=i;
        sort(side+1,side+a+1,comp);
        for(int i=1;i<=a;i++)
        {
            int u=side[i].u;
            int g=side[i].v;
            if(ga(u)!=ga(g))
            {
                fa[ga(u)]=ga(g);
                ans+=1LL*(side[i].k);
                numy++;
            }
        }
        for(int i=1;i<=q;i++)
        {
            v=read();
            cout<<ans+1LL*numy*v<<endl;
        }
    }
}

std.cpp

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    char ch=getchar();int i=0,f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
    return i*f;
}
inline void W(long long x){
    static int buf[50];
    if(!x){putchar('0');return;}
    if(x<0){putchar('-');x=-x;}
    while(x){buf[++buf[0]]=x%10;x/=10;}
    while(buf[0])putchar(buf[buf[0]--]+'0');
}
const int Maxn=1e5+50; 
const int INF=0x3f3f3f3f;
int n,Acnt,Bcnt,q,anc[Maxn];
long long ans[Maxn],sum;
struct node{
    node *lc,*rc,*fa,*mxid;
    int val,mx,x,y,revtag;
    inline void rev(){
        revtag^=1;
        swap(lc,rc);
    }
    inline void pushdown(){
        if(!revtag)return;
        if(lc)lc->rev();
        if(rc)rc->rev();
        revtag^=1;
    }
    inline void upt(){
        mxid=this;mx=val;
        if(lc&&lc->mx>mx)mxid=lc->mxid,mx=lc->mx;
        if(rc&&rc->mx>mx)mxid=rc->mxid,mx=rc->mx;
    }
}Pool[Maxn<<2],*pool=Pool,*pos[Maxn];
inline node* newnode(int v,int x,int y){
    ++pool;
    pool->lc=NULL;pool->rc=NULL;pool->fa=NULL;
    pool->val=v;pool->mx=v;pool->mxid=pool;
    pool->x=x;pool->y=y;
    return pool;
}
struct E{
    int x,y,w;
    friend inline bool operator <(const E &a,const E &b){
        return a.w<b.w;
    } 
}A[Maxn<<1],B[Maxn<<1];
struct E2{
    int x,y,w,low,rpc;
    inline bool operator =(const E &b){
        x=b.x,y=b.y,w=b.w;
    }
}Bnow[Maxn];
struct Q{
    int v,id;
}qry[Maxn];
inline bool cmpv(const Q &a,const Q &b){return a.v<b.v;}
inline bool cmpw(const E2 &a,const E2 &b){return a.w<b.w;}
inline bool cmplow(const E2 &a,const E2 &b){return a.low<b.low;}
inline int getanc(int x){return (anc[x]==x)?(x):(anc[x]=getanc(anc[x]));}
inline bool isroot(node *x){
    return !x->fa||(x->fa->lc!=x&&x->fa->rc!=x);
}
inline bool which(node *x){
    return x->fa->lc==x;
}
inline void rotate(node *x){
    node *y=x->fa,*z=y->fa;
    if(!isroot(y))(z->lc==y?z->lc:z->rc)=x;
    x->fa=z;y->fa=x;
    if(y->lc==x){
        node *b=x->rc;
        x->rc=y;
        y->lc=b;
        if(b)b->fa=y;
    }else{
        node *b=x->lc;
        x->lc=y;
        y->rc=b;
        if(b)b->fa=y;
    }
    y->upt();x->upt();
}
inline void splay(node *x){
    static node* que[Maxn];
    static int tail;
    que[tail=1]=x;
    for(node* y=x;!isroot(y);y=y->fa)que[++tail]=y->fa;
    for(int i=tail;i>=1;i--)que[i]->pushdown();
    while(!isroot(x)){
        node *y=x->fa;
        if(!isroot(y)){
            if(which(y)^which(x))rotate(y);
            else rotate(x);
        }
        rotate(x);
    }
}
inline void access(node *x){
    for(node *y=NULL;x;y=x,x=x->fa){
        splay(x);x->rc=y;x->upt();
        if(y)y->fa=x;
    }
}
inline void makeroot(node *x){
    access(x);splay(x);x->rev();
}
inline node* findmx(node *x,node *y){
    makeroot(x);access(y);splay(y);
    return y->mxid;
}
inline void Cut(node *x,node *y){
    makeroot(x);access(y);splay(y);
    y->lc->fa=NULL;y->lc=NULL;y->upt();
}
inline void Link(node *x,node *y){
    makeroot(x);x->fa=y;
}
int main(){
    n=read(),Acnt=read(),Bcnt=read(),q=read();
    for(int i=1;i<=Acnt;i++){
        A[i].x=read(),A[i].y=read(),A[i].w=read();
    }
    for(int i=1;i<=Bcnt;i++){
        B[i].x=read(),B[i].y=read(),B[i].w=read();
    }
    sort(A+1,A+Acnt+1);sort(B+1,B+Bcnt+1);
    for(int i=1;i<=n;i++)pos[i]=newnode(-INF,0,0);
    int head=1;
    for(int i=1;i<=n;i++)anc[i]=i;
    for(int i=1;i<n;i++){
        while(getanc(A[head].x)==getanc(A[head].y))++head;
        anc[getanc(A[head].x)]=getanc(A[head].y);
        node *t=newnode(A[head].w,A[head].x,A[head].y);
        Link(pos[A[head].x],t);Link(pos[A[head].y],t);
        sum+=A[head].w;++head;
    }
    head=1;int tot=0;
    for(int i=1;i<=n;i++)anc[i]=i;
    for(int i=1;i<n;i++){
        while(getanc(B[head].x)==getanc(B[head].y))++head;
        anc[getanc(B[head].x)]=getanc(B[head].y);
        Bnow[i]=B[head++];
    }
    sort(Bnow+1,Bnow+tot+1,cmpw);
    for(int i=1;i<n;i++){
        node *t=findmx(pos[Bnow[i].x],pos[Bnow[i].y]);
        if(t->val<=-INF){Bnow[i].low=INF;}
        else{
            Bnow[i].low=(Bnow[i].w-t->val+1)/2;
            Bnow[i].rpc=t->val;
            Cut(t,pos[t->x]);Cut(t,pos[t->y]);
            t=newnode(-INF,0,0);
            Link(pos[Bnow[i].x],t);Link(pos[Bnow[i].y],t);
        }
    }
    sort(Bnow+1,Bnow+n,cmplow);
    for(int i=1;i<=q;i++)qry[i].v=read(),qry[i].id=i;
    sort(qry+1,qry+q+1,cmpv);
    int cntB=0;head=0;
    for(int i=1;i<=q;i++){
        while(head<n-1&&Bnow[head+1].low<=qry[i].v){
            ++head;cntB++;
            sum+=Bnow[head].w;sum-=Bnow[head].rpc;
        }
        ans[qry[i].id]=sum+1ll*(n-1-2*cntB)*qry[i].v;
    }
    for(int i=1;i<=q;i++){
        W(ans[i]);putchar('\n');
    }
}
# P11362 [NOIP2024] 遗失的赋值 ## 题目描述 小 F 有 $n$ 个变量 $x_1, x_2, \ldots , x_n$。每个变量可以取 $1$ 至 $v$ 的整数取值。 小 F 在这 $n$ 个变量之间添加了 $n - 1$ 条二元限制,其中第 $i$($1 \leq i \leq n - 1$)条限制为:若 $x_i = a_i$,则要求 $x_{i+1} = b_i$,**且 $a_i$ 与 $b_i$ 为 $1$ 到 $v$ 之间的整数**;当 $x_i \neq a_i$ 时,第 $i$ 条限制对 $x_{i+1}$ 的值不做任何约束。除此之外,小 F 还添加了 $m$ 条一元限制,其中第 $j$($1 \leq j \leq m$)条限制为:$x_{c_j} = d_j$。 小 F 记住了所有 $c_j$ 和 $d_j$ 的值,但把所有 $a_i$ 和 $b_i$ 的值都忘了。同时小 F 知道:存在给每一个变量赋值的方案同时满足所有这些限制。 现在小 F 想知道,有多少种 $a_i, b_i$($1 \leq i \leq n - 1$)取值的组合,使得能够确保至少存在一种给每个变量 $x_i$ 赋值的方案可以同时满足所有限制。由于方案数可能很大,小 F 只需要你输出方案数对 $10^9 + 7$ 取模的结果。 ## 输入格式 **本题包含多组测试数据**。 输入的第一行包含一个整数 $T$,表示测试数据的组数。 接下来包含 $T$ 组数据,每组数据的格式如下: 第一行包含三个整数 $n, m, v$,分别表示变量个数、一元限制个数和变量的取值上限。 接下来 $m$ 行,第 $j$ 行包含两个整数 $c_j, d_j$,描述一个一元限制。 ## 输出格式 对于每组测试数据输出一行,包含一个整数,表示方案数对 $10^9 + 7$ 取模的结果。 ## 输入输出样例 #1 ### 输入 #1 ``` 3 2 1 2 1 1 2 2 2 1 1 2 2 2 2 2 1 1 1 2 ``` ### 输出 #1 ``` 4 3 0 ``` ## 说明/提示 **【样例 1 解释】** - 对于第一组测试数据,所有可能的 $(a_1, b_1)$ 取值的组合 $(1, 1), (1, 2), (2, 1), (2, 2)$ 都满足限制。例如,$(a_1, b_1) = (1, 1)$ 时,$(x_1, x_2) = (1, 1)$ 满足所有限制,而 $(a_1, b_1) = (2, 2)$ 时,$(x_1, x_2) = (1, 1)$ 与 $(x_1, x_2) = (1, 2)$ 均满足所有限制。 - 对于第二组测试数据,只有 $(x_1, x_2) = (1, 2)$ 一种可能的变量赋值,因此只有 $(a_1, b_1) = (1, 1)$ 不满足限制,其余三种赋值均满足限制。 - 对于第三组测试数据,不存在一种变量赋值同时满足 $x_1 = 1$ 和 $x_1 = 2$,因此也不存在满足限制的 $(a_1, b_1)$。 **【样例 2】** 见选手目录下的 `assign/assign2.in` 与 `assign/assign2.ans`。 该样例共有 $10$ 组测试数据,其中第 $i$($1 \leq i \leq 10$)组测试数据满足数据范围中描述的测试点 $i$ 的限制。 **【样例 3】** 见选手目录下的 `assign/assign3.in` 与 `assign/assign3.ans`。 该样例共有 $10$ 组测试数据,其中第 $i$($1 \leq i \leq 10$)组测试数据满足数据范围中描述的测试点 $i + 10$ 的限制。 **【数据范围】** 对于所有的测试数据,保证: - $1 \leq T \leq 10$, - $1 \leq n \leq 10^9$,$1 \leq m \leq 10^5$,$2 \leq v \leq 10^9$, - 对于任意的 $j$($1 \leq j \leq m$),都有 $1 \leq c_j \leq n$,$1 \leq d_j \leq v$。 ::cute-table{tuack} | 测试点 | $n \leq$ | $m \leq$ | $v \leq$ | 特殊性质 | | :----------: | :----------: | :----------: | :----------: | :----------: | | $1, 2$ | $6$ | $6$ | $2$ | 无 | | $3$ | $9$ | $9$ | ^ | ^ | | $4, 5$ | $12$ | $12$ | ^ | ^ | | $6$ | $10^3$ | $1$ | $10^3$ | ^ | | $7$ | $10^5$ | ^ | $10^5$ | ^ | | $8,9$ | $10^9$ | ^ | $10^9$ | ^ | | $10$ | $10^3$ | $10^3$ | $10^3$ | A | | $11$ | $10^4$ | $10^4$ | $10^4$ | ^ | | $12$ | $10^5$ | $10^5$ | $10^5$ | ^ | | $13$ | $10^4$ | $10^3$ | $10^4$ | B | | $14$ | $10^6$ | $10^4$ | $10^6$ | ^ | | $15, 16$ | $10^9$ | $10^5$ | $10^9$ | ^ | | $17$ | $10^4$ | $10^3$ | $10^4$ | 无 | | $18$ | $10^6$ | $10^4$ | $10^6$ | ^ | | $19, 20$ | $10^9$ | $10^5$ | $10^9$ | ^ | 特殊性质 A:保证 $m = n$,且对于任意的 $j$($1 \leq j \leq m$),都有 $c_j = j$。 特殊性质 B:保证 $d_j = 1$。C++代码
最新发布
08-29
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值