zoukankan      html  css  js  c++  java
  • 20190730 NOIP模拟测试10「辣鸡·模板·大佬」

    说实话,真心不想写,考得太差了,35分,rank34/55

    不过反思、题解还是要写的

    考试的时候看见T2 「 模板 」,绝对没那么简单,直接跳,先做的T1,花了两个小时,又花了一个多小时搞T3,T2就这样丢了,结果T3爆零,自我感觉能AC的T1只拿了35

    总结几点:

    1.永远不要寄希望于某一道题,更不要死磕

    2.把握时间分配,如Deepinc所说,先评估难度,大概半小时左右把最简单的搞出来,在去想难一点儿的,半个小时还没有思路就有啥思路打啥

    3.期望放低,失望的概率会小,在博客里疯狂踩自己可以拿Rank1 QWQ

    T1 辣鸡

      n^2大暴搜,一个(x*y)的块里面有(x-1)*(y-1) 个氢键,再讨论块与块之间的氢键数量,接触的部分的块的个数d,为(d-1)*2,如果除了接触的部分,有一端出头数量+1,

    有两端出头则+2

      Ps: 做题时考虑仔细,不要漏掉任何情况

      Pss:一定按照题中给出的坐标系的形式建图,比如此题x是横坐标,y是纵坐标,不要像我一样把坐标系翻转,按y排序导致被卡

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define ll long long
    int n;
    struct node{
        ll u,l,d,r;
    }q[110000];
    inline int cmp(node a,node b){
        return a.l<b.l;
    }
    long long ans;
    int main(){
        scanf("%d",&n);
        for(register int i=1;i<=n;i++){
            scanf("%lld%lld%lld%lld",&q[i].l,&q[i].d,&q[i].r,&q[i].u);
            ans+=(ll)(q[i].u-q[i].d)*(q[i].r-q[i].l)*2;
        }
        //cout<<ans<<endl;
        sort(q+1,q+n+1,cmp);
        for(register int i=1;i<n;i++){
            for(register int j=i+1;j<=n&&q[i].r+1>=q[j].l;j++){
                int minn;
            //    cout<<i<<" "<<j<<endl;
                if(q[j].l==q[i].l){
                    if(q[j].u+1==q[i].d||q[j].d-1==q[i].u){
                        minn=min(q[i].r-q[i].l+1,q[j].r-q[j].l+1);
                        ans+=(minn-1)*2;
                        if(q[j].r!=q[i].r) ans++;
                    }
                }
                else if(q[j].l<=q[i].r){
                    if(q[j].u+1==q[i].d||q[j].d-1==q[i].u){
                        if(q[j].r>q[i].r) minn=q[i].r-q[j].l+1;
                        else if(q[j].r<q[i].r) minn=q[j].r-q[j].l+1;
                        else minn=q[i].r-q[j].l+1;
                        ans+=(minn-1)*2;
                        ans+=(q[j].r==q[i].r)?1:2;
                    }
                }
                else if(q[i].r+1==q[j].l){
                    if(q[j].u==q[i].d-1||q[j].d==q[i].u+1) ans++;
                    else if(q[j].u<q[i].u&&q[j].u>=q[i].d){
                        if(q[j].d>q[i].d) minn=q[j].u-q[j].d+1;
                        else if(q[j].d<q[i].d) minn=q[j].u-q[i].d+1;
                        else if(q[j].d==q[i].d) minn=q[j].u-q[i].d+1;
                        ans+=(minn-1)*2;
                        ans+=(q[j].d==q[i].d)?1:2;
                    }
                    else if(q[j].u>q[i].u&&q[i].u>=q[j].d){
                        if(q[j].d>q[i].d) minn=q[i].u-q[j].d+1;
                        else if(q[j].d<q[i].d) minn=q[i].u-q[i].d+1;
                        else if(q[j].d==q[i].d) minn=q[i].u-q[j].d+1;
                        ans+=(minn-1)*2;
                        ans+=(q[j].d==q[i].d)?1:2;  
                    }
                    else if(q[j].u==q[i].u){
                        if(q[j].d>q[i].d) minn=q[i].u-q[j].d+1;
                        else if(q[j].d<q[i].d) minn=q[i].u-q[i].d+1;
                        else minn=q[i].u-q[i].d+1;
                        ans+=(minn-1)*2;
                        ans+=(q[j].d==q[i].d)?0:1;
                    }
                }
            }
        }
        printf("%lld
    ",ans);
    }
    View Code

    T2 模板

      线段树维护区间球的个数,颜色的个数,查询时查询球数是该点桶的数量的区间(从1~?)的颜色数

      颜色要离散化,因为有负数而且颜色值可能会很大

      线段树用启发式合并,即保留最大子树的信息,加上其他子树更新当前节点的信息

      PS:注意询问函数的答案统计和递归边界,否则会死循环

      PS:注意每次处理完一个节点且这个节点信息不保留,清零最好用时间戳(也就是f懒标记)清空,一定不能用memset   

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    #include<map>
    using namespace std;
    int n,m,Q,num,cet,root;
    const int maxn=1e5+100;
    int ls[410000],rs[410000],f[410000],qiunum[410000],colornum[410000],w[maxn],size[maxn],ma[maxn],is_here[maxn],loc[maxn],wolan[maxn],key[maxn];
    vector<int>son[110000],point[110000];
    int tmp[maxn],ans[maxn];
    inline void down(int t){
        qiunum[ls[t]]=colornum[ls[t]]=0;
        qiunum[rs[t]]=colornum[rs[t]]=0;
        f[ls[t]]=f[rs[t]]=1;
        if(ls[ls[t]]==0&&rs[ls[t]]==0) f[ls[t]]=0;
        if(ls[rs[t]]==0&&rs[rs[t]]==0) f[rs[t]]=0;
        f[t]=0;
    }
    inline void build(int  &t,int l,int r){
        if(!t) t=++cet;
         if(l==r) return ;
        int mid=(l+r)/2;
        build(ls[t],l,mid);
        build(rs[t],mid+1,r);
    }
    inline void dfs1(int x,int pre){
        size[x]=1+point[x].size();
        int mxn=0;
        for(register int i=0;i<son[x].size();i++){
            int y=son[x][i];
            if(y==pre) continue;
            dfs1(y,x);
            size[x]+=size[y];
            if(size[y]>mxn) ma[x]=y,mxn=size[y];
        }
    }
    inline void change(int t,int l,int r,int x){
        if(l==r){
            colornum[t]=0;
            return;
        }
        if(f[t]) down(t);
        int mid=(l+r)/2;
        if(mid>=x) change(ls[t],l,mid,x);
        else change(rs[t],mid+1,r,x);
        qiunum[t]=qiunum[ls[t]]+qiunum[rs[t]];
        colornum[t]=colornum[ls[t]]+colornum[rs[t]];
    }
    int landenum;
    inline void add(int t,int l,int r,int x,int k){
        if(l==r){
            qiunum[t]+=k;
            colornum[t]+=k;
            if(wolan[w[l]]!=landenum) wolan[w[l]]=0,is_here[w[l]]=0,loc[w[l]]=0;
            if(k==1&&!is_here[w[l]]) is_here[w[l]]=1,loc[w[l]]=l,wolan[w[l]]=landenum;
            else if(k==1&&is_here[w[l]]){
                if(loc[w[l]]<l)  colornum[t]=0;
                else{
                    change(1,1,m,loc[w[l]]);
                    loc[w[l]]=l;
                }
            }
            return;
        }
        if(f[t]) down(t);
        int mid=(l+r)/2;
        if(mid>=x) add(ls[t],l,mid,x,k);
        else add(rs[t],mid+1,r,x,k);
        qiunum[t]=qiunum[ls[t]]+qiunum[rs[t]];
        colornum[t]=colornum[ls[t]]+colornum[rs[t]];
    }
    inline void go_add(int x,int pre,int k){
        for(register int i=0;i<point[x].size();i++)
            add(1,1,m,point[x][i],k);
        for(register int i=0;i<son[x].size();i++)
             if(son[x][i]!=pre)
                  go_add(son[x][i],x,k);
    }
    inline int ask(int t,int x){
        if(x==0) return 0;
        if(qiunum[t]==0) return 0;
        if(t==0) return 0;
        if(qiunum[t]<x) return colornum[t];
        if(qiunum[t]==x) return colornum[t];
        if(qiunum[ls[t]]==x) return colornum[ls[t]];
        else if(qiunum[ls[t]]>x) return ask(ls[t],x);
        return colornum[ls[t]]+ask(rs[t],x-qiunum[ls[t]]);
    }
    inline void dfs(int x,int keep,int pre){
        landenum++;
        for(register int i=0;i<son[x].size();i++){
            int y=son[x][i];
            if(y==pre||y==ma[x]) continue;
            dfs(y,0,x);
        }
        if(ma[x]) dfs(ma[x],1,x);
        for(register int i=0;i<point[x].size();i++)
            add(1,1,m,point[x][i],1);
        for(register int i=0;i<son[x].size();i++){
            int y=son[x][i];
            if(y==pre||y==ma[x]) continue;
            go_add(son[x][i],x,1);
        }
        ans[x]=ask(1,tmp[x]);
        if(!keep){
            f[1]=1,qiunum[1]=0,colornum[1]=0;
        }
    }
    int main(){
        scanf("%d",&n);
        int  x,y;
        for(register int i=1;i<n;i++){
            scanf("%d%d",&x,&y);
            son[x].push_back(y);
            son[y].push_back(x);
        }
        for(register int i=1;i<=n;i++)
            scanf("%d",&tmp[i]);
        scanf("%d",&m);
        build(root,1,m);
        for(register int i=1;i<=m;i++){
            scanf("%d%d",&x,&y);
            w[i]=key[i]=y;
            point[x].push_back(i);
        }
        cout<<endl;
        sort(key+1,key+m+1);
        int q=unique(key+1,key+m+1)-key- 1;
        for(register int i=1;i<=m;i++){
            w[i]=lower_bound(key+1,key+q+1,w[i])-key;
        }
        dfs1(1,0);
        dfs(1,0,0);
        scanf("%d",&Q);
        while(Q--){
            scanf("%d",&x);
            printf("%d
    ",ans[x]);
        }
        return 0;
    }
    View Code

    T3 大佬

      有一个完全组合数学的思路,对于n道题的难度,方案数是n^m,而这每一种方案对应一种第一天……,第二天……,第三天……的情况

      所以每天的方案是一样的,概率也一样,n天的期望就是一天的期望乘上n天

      另一种理解,额~就叫他加法结合律吧

                                                               

      直观上看起来二者是相等的

      所以n天的期望等于一天期望乘上n天

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define ll long long
    const int mod=1e9+7;
    int n,m,k;
    ll wt[650],f[2][450],sum;
    ll pow(ll a,ll b){
        ll ans=1;
        a%=mod;
        while(b){
            if(b&1) ans=ans*a%mod;
            b>>=1;
            a=a*a%mod;
        }
        return ans%mod;
    }
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        if(k>n){
            puts("0");
            return 0;
        }
        for(int i=1;i<=m;i++){
            scanf("%lld",&wt[i]);
             if(i!=1) wt[i]=wt[i]%mod*(pow(i,k)-pow(i-1,k)+mod)%mod;
            sum=(sum+wt[i])%mod;
        }
        ll ans=pow(pow(m,k),mod-2)%mod;
        printf("%lld
    ",sum*(n-k+1)%mod*ans%mod);
    }
    View Code
  • 相关阅读:
    8天学通MongoDB(实际操作版)——第九天 构建学习型部署环境
    构建Ubuntu Server试验环境
    8天学通MongoDB(实际操作版)——第一天 基础入门
    《JAVA与模式》之适配器模式
    wsdl
    Axis2 Fault: Transport out has not been set
    诺基亚E63常见设置指南
    java面试题总结
    R400 安装XP后 ati2dvag蓝屏解决办法
    深入理解Java多态性
  • 原文地址:https://www.cnblogs.com/heoitys/p/11273807.html
Copyright © 2011-2022 走看看