首页 > 其他 > 详细

[总结] NOIP 前的考试记录

时间:2018-07-13 23:58:47      阅读:287      评论:0      收藏:0      [点我收藏+]

写在前面

由于我天天被虐,模拟考还老是考的极差,感觉有必要开个博客记录一下每场考试

由于懒得加美元符所以这篇博客不用 latex

由于要弄代码折叠我还特意换掉了 Markdown 编辑器

由于我没话说了,前言就这么多吧

 

2018.7.13

开场看 T1 发现不会顿时贼虚,思路明明马上就是正解了但是死活没想出来。把点权放到边上求出来最大生成树之后立马敲了个树剖(我只是生来码农) 然后跟暴力一样 n^2 求的两点边权最小值

看 T2 也是发现性质可以开两个树状数组做但是死活没想出来答案从哪找,结果发现莫队一脸可做码了个带修莫队还把块大小设成根号 n 了。(我果然菜到连前一天刚讲过的板子都不会敲了

结果 T2 被卡但是还是比暴力多 20 分

T3 更不可做 直接30分爆搜走人

总分 50+50+30=130  本部 rank3/16

T1 这东西应该能发现可以从大到小加边合并集合啊这不跟走廊泼水节一样么

技术分享图片
#include<cstdio>
#include<cctype>
#include<algorithm>
#define N 100005
#define int long long
#define min(A,B) ((A)<(B)?(A):(B))
#define max(A,B) ((A)>(B)?(A):(B))
#define swap(A,B) ((A)^=(B)^=(A)^=(B))

int val[N];
int father[N];
int d[N],fa[N];
int n,m,cnt,tot;
int cme[N],fs[N];
int sze[N],son[N];
int dfn[N],top[N];
int head[N],mn[N<<2];

struct Edge{
    int to,nxt,dis;
}edge[N<<1];

void add(int x,int y,int z){
    edge[++cnt].to=y;
    edge[cnt].nxt=head[x];
    edge[cnt].dis=z;
    head[x]=cnt;
}

struct Node{
    int x,y,dis;
    friend bool operator<(Node a,Node b){
        return a.dis>b.dis;
    }
}node[N*10];

int getint(){
    int x=0,f=0;char ch=getchar();
    while(!isdigit(ch)) f|=ch==-,ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?-x:x;
}

int find(int x){
    if(father[x]==x) return x;
    return father[x]=find(father[x]);
}

void file(){
    freopen("zoo.in","r",stdin);
    freopen("zoo.out","w",stdout);
}

signed main(){
    file();
    n=getint(),m=getint();
    for(int i=1;i<=n;i++){
        father[i]=i;
        sze[i]=1;
        val[i]=getint();
    }
    for(int i=1;i<=m;i++){
        node[i].x=getint();
        node[i].y=getint();
        node[i].dis=min(val[node[i].x],val[node[i].y]);
    } int now=0;
    std::sort(node+1,node+1+m);
    for(int i=1;i<=m;i++){
        int x=find(node[i].x);
        int y=find(node[i].y);
        if(x==y) continue;
        father[x]=y;
        now+=sze[x]*sze[y]*node[i].dis;
        sze[y]+=sze[x];
    }
    printf("%lld\n",now<<1);
    return 0;
}
View Code

T2 可以开两个树状数组分别存每个点之前线段左、右端点各出现了多少次。

然后查询就是用右端点之前出现了多少次减去左端点减一之前出现了多少次

技术分享图片
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define N 200005
#define min(A,B) ((A)<(B)?(A):(B))
#define max(A,B) ((A)>(B)?(A):(B))
#define swap(A,B) ((A)^=(B)^=(A)^=(B))

int tot,cnt;
int g[N<<1];
int l[N],r[N];
int T,n,cas,m;
int ques[N][5];
int xgl[N],xgr[N];

struct BIT{
    int f[N<<1];

    void clear(){
        memset(f,0,sizeof f);
    }

    int query(int x){
        int ans=0;
        for(;x>=1;x-=x&-x)
            ans+=f[x];
        return ans;
    }

    void add(int x,int y){
        for(;x<=m;x+=x&-x)
            f[x]+=y;
    }

}a,b;

int getint(){
    int x=0,f=0;char ch=getchar();
    while(!isdigit(ch)) f|=ch==-,ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?-x:x;
}

signed main(){
    freopen("segment.in","r",stdin);
    freopen("segment.out","w",stdout);
    T=getint();
    while(T--){
        a.clear();b.clear();
        cnt=tot=0;
        n=getint();
        for(int i=1;i<=n;i++){
            ques[i][1]=getint();
            ques[i][2]=getint();
            if(ques[i][1]){
                xgl[i]=l[ques[i][2]];
                xgr[i]=r[ques[i][2]];
            } else{
                cnt++;
                ques[i][3]=ques[i][2]+cnt;
                l[cnt]=ques[i][2];
                r[cnt]=ques[i][3];
                g[++tot]=ques[i][2];
                g[++tot]=ques[i][3];
            }
        }
        std::sort(g+1,g+1+tot);
        m=std::unique(g+1,g+1+tot)-g-1;
        printf("Case #%d:\n",++cas);
        for(int i=1;i<=n;i++){
            if(ques[i][1]==0){
                ques[i][2]=std::lower_bound(g+1,g+1+m,ques[i][2])-g;
                ques[i][3]=std::lower_bound(g+1,g+1+m,ques[i][3])-g;
                printf("%d\n",b.query(ques[i][3])-a.query(ques[i][2]-1));
                a.add(ques[i][2],1);
                b.add(ques[i][3],1);
            } else{
                xgl[i]=std::lower_bound(g+1,g+1+m,xgl[i])-g;
                xgr[i]=std::lower_bound(g+1,g+1+m,xgr[i])-g;
                a.add(xgl[i],-1);
                b.add(xgr[i],-1);
            }
        }
    }
    return 0;
}
View Code

T3 什么鬼啊喂 2^((n-1)*(m-1)-k) 是啥啊 noip 压轴题靠打表的啊啊啊?

证明:不会(×)

技术分享图片
#include<cstdio>
#include<cctype>
#include<cstring>
#define int long long
#define min(A,B) ((A)<(B)?(A):(B))
#define max(A,B) ((A)>(B)?(A):(B))
#define swap(A,B) ((A)^=(B)^=(A)^=(B))

int k;
int n,m,p;

int ksm(int a,int b){
    int ans=1;
    if(b<0) return ans;
    while(b){
        if(b&1) ans=ans*a%p;
        a=a*a%p;
        b>>=1;
    }
    return ans;
}

int getint(){
    int x=0,f=0;char ch=getchar();
    while(!isdigit(ch)) f|=ch==-,ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?-x:x;
}

signed main(){
    freopen("number.in","r",stdin);
    freopen("number.out","w",stdout);
    n=getint();m=getint();k=getint();
    for(int i=1;i<=k;i++)
        int a=getint(),b=getint(),c=getint();
    p=getint();
    if((n+m)%2==1) return printf("0"),0;
    printf("%lld\n",ksm(2,(n-1)*(m-1)-k));
    return 0;
}
View Code

 

[总结] NOIP 前的考试记录

原文:https://www.cnblogs.com/YoungNeal/p/9307950.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!