zoukankan      html  css  js  c++  java
  • 2015长春网络赛总结

    2015长春网络赛总结

    1007:签到题,区间最值查询,暴力或线段树或者ST都行。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define RI(a) scanf("%d",&(a))
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    
    int n,a[maxn];
    int l,r;
    int q;
    int Max[maxn<<2];
    
    void push_up(int rt)
    {
        Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
    }
    
    void build(int l,int r,int rt)
    {
        if(l==r){
            RI(Max[rt]);
            //cout<<l<<" "<<r<<" "<<rt<<" "<<Max[rt]<<endl;
            return;
        }
        int m=(l+r)>>1;
        build(lson);
        build(rson);
        push_up(rt);
    }
    
    int query(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&r<=R) return Max[rt];
        int m=(l+r)>>1;
        int res=-INF;
        if(L<=m) res=max(res,query(L,R,lson));
        if(R>m) res=max(res,query(L,R,rson));
        return res;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T;cin>>T;
        while(T--){
            RI(n);
            //cout<<"_"<<n<<endl;
            build(1,n,1);
            RI(q);
            //cout<<"__"<<q<<endl;
            while(q--){
                RI(l);RI(r);
                //cout<<l<<" "<<r<<" ";
                printf("%d
    ",query(l,r,1,n,1));
            }
        }
        return 0;
    }
    View Code

    过了签到题后,接着就悲剧了。。。。。。。。。。。。。。

    1010:lucas+中国剩余定理。。。

    求大组合数对几个不同的素数乘积取模。

    比赛的时候翻了一下紫书,看到了中国剩余定理,对着题目脑补了一下,出了思路。然而。。。于是打开博客找lucas模板,有从网上复制了中国剩余定理的模板,交上去TLE了。。然后把lucas模板换成了预处理阶乘版本的,再交WA了。。然后一直调。。。一直换模板。。。赛后发现是lucas模板不预处理阶乘版本的会TLE,之后的完全不是模板的问题,自己将预处理阶乘时的p取成了100007,以为是素数。。。100007居然不是素数!!!。。。。。另一个注意点就是剩余定理的模板上有个三个10^18相乘对10^18的情况,会爆longlong,需要模拟乘法,这点比赛的时候倒是注意到了。。。。赛后把p从100007换成素数就过了。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define RI(a) scanf("%d",&(a))
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    
    ll n,m,k;
    ll p[maxn],b[maxn];
    ll F[maxn];
    
    void Init(ll p)
    {
        F[0]=1;
        REP(i,1,p) F[i]=(F[i-1]*i)%p;
    }
    
    ll mul(ll a,ll b,ll p)
    {
        ll res=0;
        while(b){
            if(b&1) res=(res+a)%p;
            a=(a+a)%p;
            b>>=1;
        }
        return res;
    }
    
    ll inv(ll a,ll m)
    {
        if(a==1) return 1;
        return inv(m%a,m)*(m-m/a)%m;
    }
    
    ll lucas(ll n,ll m,ll p)
    {
        ll ans=1;
        while(n&&m){
            ll a=n%p;
            ll b=m%p;
            if(a<b) return 0;
            ans=ans*F[a]%p*inv(F[b]*F[a-b]%p,p)%p;
            n/=p;m/=p;
        }
        return ans;
    }
    
    void gcd(ll a,ll b,ll &d,ll &x,ll &y)
    {
        if(!b){
            b=a;x=1;y=0;
        }
        else{
            gcd(b,a%b,d,y,x);
            y-=x*(a/b);
        }
    }
    
    ll china(ll n,ll *a,ll *m)
    {
        ll M=1,d,y,x=0;
        REP(i,0,n-1) M*=m[i];
        REP(i,0,n-1){
            ll w=M/m[i];
            gcd(m[i],w,d,d,y);
            x=(x+mul(y,mul(w,a[i],M),M))%M;
        }
        return (x+M)%M;
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        int T;cin>>T;
        while(T--){
            scanf("%I64d%I64d%I64d",&n,&m,&k);
            REP(i,0,k-1){
                scanf("%d",&p[i]);
                Init(p[i]);
                b[i]=lucas(n,m,p[i]);
            }
            printf("%I64d
    ",china(k,b,p));
        }
    }
    View Code

    1005:离线并查集。

    对所有的询问离线和边排序一下就好了。

    这题比赛的时候是队友写的,居然意外地没过!!!!!!!!都怪自己傻逼一直调1010,浪费了大部分时间,要是先把1010暂放,去帮队友调这题肯定就过了。。。。后来本来也有时间,被队友叫去写1001题的傻逼模拟了,而且在思路没理清的时候就写了,也没注意坑点。。。。悲剧。。。。。。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define RI(a) scanf("%d",&(a))
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    
    int N,M,Q;
    struct Edge
    {
        int u,v,w;/// id isEdge ask
        int ans;
        friend bool operator<(Edge A,Edge B)
        {
            if(A.w<B.w) return 1;
            if(A.w==B.w) return A.v>B.v;
            return 0;
        }
    };
    Edge e[maxn];
    Edge q[maxn];
    Edge eq[maxn];
    int cnt;
    int fa[maxn];
    int sum[maxn];
    
    bool cmpID(Edge A,Edge B)
    {
        return A.u<B.u;
    }
    
    int Find(int x)
    {
        return fa[x]==x?x:fa[x]=Find(fa[x]);
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        int T;cin>>T;
        while(T--){
            scanf("%d%d%d",&N,&M,&Q);
            REP(i,1,M) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
            REP(i,1,Q) scanf("%d",&q[i].w),q[i].u=i,q[i].v=-1;
            cnt=0;
            REP(i,1,M) eq[++cnt]=e[i];
            REP(i,1,Q) eq[++cnt]=q[i];
            sort(eq+1,eq+cnt+1);
            REP(i,0,maxn-1) fa[i]=i;
            REP(i,1,N) sum[i]=1;
            int Ans=0;
            REP(i,1,cnt){
                if(eq[i].v!=-1){
                    int u=eq[i].u,v=eq[i].v,w=eq[i].w;
                    int x=Find(u),y=Find(v);
                    if(x!=y){
                        Ans-=sum[y]*(sum[y]-1)+sum[x]*(sum[x]-1);
                        sum[x]+=sum[y];
                        sum[y]=0;
                        fa[y]=x;
                        Ans+=sum[x]*(sum[x]-1);
                    }
                }
                else eq[i].ans=Ans;
            }
            Q=0;
            REP(i,1,cnt){
                if(eq[i].v==-1) q[++Q]=eq[i];
            }
            sort(q+1,q+Q+1,cmpID);
            REP(i,1,Q) printf("%d
    ",q[i].ans);
        }
        return 0;
    }
    View Code

    1001:优先队列模拟。

    直接优先队列模拟一下就行了,注意最后没进去的都要按权值进去,当时问了一下队友是不是按标号进去的,队友说是,郁闷。。。还有询问是不按顺序的。。。。模拟题最重要的就是防坑。比赛的时候真是一片混乱,写完就交,根本没意识关注这些坑点,一直卡到比赛结束。。。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #include<algorithm>
    #define RI(a) scanf("%d",&(a))
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    const int maxn=150100;
    const int INF=(1<<29);
    
    struct Node
    {
        char s[210];
        int val,t;
        friend bool operator<(Node A,Node B)
        {
            if(A.val<B.val) return 1;
            if(A.val==B.val) return A.t>B.t;
            return 0;
        }
    };
    int N,M,Q;
    int x;
    Node a[maxn];
    struct Ask
    {
        int t,c;
        friend bool operator<(Ask A,Ask B)
        {
            return A.t<B.t;
        }
    };
    Ask ask[maxn];
    
    int main()
    {
        freopen("in.txt","r",stdin);
        int T;cin>>T;
        while(T--){
            scanf("%d%d%d",&N,&M,&Q);
            REP(i,1,N){
                scanf("%s%d",a[i].s,&a[i].val);
                a[i].t=i;
            }
            REP(i,1,M){
                scanf("%d%d",&ask[i].t,&ask[i].c);
            }
            sort(ask+1,ask+M+1);
            priority_queue<Node> q;
            vector<Node> ans;
            int tot=1;
            REP(i,1,M){
                while(tot<=N&&a[tot].t<=ask[i].t){
                    q.push(a[tot++]);
                }
                int c=0;
                while(!q.empty()){
                    if(c==ask[i].c) break;
                    ans.push_back(q.top());
                    q.pop();
                    c++;
                }
            }
            while(tot<=N) q.push(a[tot++]);
            while(!q.empty()){
                ans.push_back(q.top());
                q.pop();
            }
            //cout<<ans.size()<<endl;
            while(Q--){
                scanf("%d",&x);
                if(Q) printf("%s ",ans[x-1].s);
                else printf("%s
    ",ans[x-1].s);
            }
        }
    }
    View Code

    1006:后缀数组。。。

    按一般循环串的处理方法,直接把前len-1个接在原串后面,然后求个后缀数组,扫一下找字典序最大的符合条件的最靠前的sa[]就行了。就是傻逼模板题啊。。。代码实现上比1001,1010要简单多了。。。。比赛的时候场面真是太混乱了,顾不上看这题了。。。

    要是早看这题,结果就会不一样了。。。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<set>
    #define RI(a) scanf("%d",&(a))
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    
    int len;
    char s[maxn],fs[maxn];
    int str[maxn];
    int n;
    int pos1,pos2;
    char ans1[maxn],ans2[maxn];
    
    int sa[maxn];
    int t1[maxn],t2[maxn],c[maxn];
    int Rank[maxn],height[maxn];
    
    void build_sa(int s[],int n,int m)
    {
        int i,j,p,*x=t1,*y=t2;
        for(i=0;i<m;i++)c[i]=0;
        for(i=0;i<n;i++)c[x[i]=s[i]]++;
        for(i=1;i<m;i++)c[i]+=c[i-1];
        for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
        for(j=1;j<=n;j<<=1)
        {
            p=0;
            for(i=n-j;i<n;i++)y[p++]=i;
            for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
            for(i=0;i<m;i++)c[i]=0;
            for(i=0;i<n;i++)c[x[y[i]]]++;
            for(i=1;i<m;i++)c[i]+=c[i-1];
            for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
            swap(x,y);
            p=1;x[sa[0]]=0;
            for(i=1;i<n;i++)
                x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
            if(p>=n)break;
            m=p;
        }
    }
    void getHeight(int s[],int n)
    {
        int i,j,k=0;
        for(i=0;i<=n;i++) Rank[sa[i]]=i;
        for(i=0;i<n;i++)
        {
            if(k)k--;
            j=sa[Rank[i]-1];
            while(s[i+k]==s[j+k])k++;
            height[Rank[i]]=k;
        }
    }
    
    void getMax1()
    {
        int p=0;
        for(int i=n;i>=1;i--){
            if(sa[i]<len){
                p=i;break;
            }
            else continue;
        }
        pos1=sa[p];
        for(int i=p;i>=2;i--){
            if(height[i]>=len){
                pos1=min(pos1,sa[i-1]);
            }
            else break;
        }
        strncpy(ans1,s+pos1,len);
    }
    
    void getMax2()
    {
        int p=0;
        for(int i=n;i>=1;i--){
            if(sa[i]<len){
                p=i;break;
            }
            else continue;
        }
        //REP(i,0,n) cout<<sa[i]<<" ";cout<<endl;
        pos2=sa[p];
        for(int i=p;i>=2;i--){
            if(height[i]>=len){
                pos2=max(pos2,sa[i-1]);
            }
            else break;
        }
        strncpy(ans2,fs+pos2,len);
        pos2=len-1-pos2;
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        int T;cin>>T;
        while(T--){
            scanf("%d%s",&len,s);
            REP(i,0,len-1) fs[i]=s[len-1-i];
            fs[len]=0;
            strncat(s,s,len-1);
            strncat(fs,fs,len-1);
            n=strlen(s);
            //cout<<s<<" "<<fs<<" "<<n<<endl;
            REP(i,0,n) str[i]=s[i];
            build_sa(str,n+1,300);
            getHeight(str,n);
            getMax1();
            REP(i,0,n) str[i]=fs[i];
            build_sa(str,n+1,300);
            getHeight(str,n);
            getMax2();
            //cout<<ans1<<" "<<ans2<<endl;
            if(strcmp(ans1,ans2)>0) printf("%d %d
    ",pos1+1,0);
            else if(strcmp(ans1,ans2)<0) printf("%d %d
    ",pos2+1,1);
            else{
                //cout<<pos1<<" "<<pos2<<endl;
                if(pos1<=pos2) printf("%d %d
    ",pos1+1,0);
                else printf("%d %d
    ",pos2+1,1);
            }
        }
        return 0;
    }
    View Code

    1007:直接模拟建树。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #define RI(a) scanf("%d",&(a))
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1000100;
    const int INF=(1<<29);
    
    int n,a;
    struct Node
    {
        int id;
        int l,r;
    };
    Node node[maxn];
    int p;
    int q,k;
    
    int go(int a,int now)
    {
        if(a<node[now].id){
            if(node[now].l==0) return now;
            return go(a,node[now].l);
        }
        else{
            if(node[now].r==0) return now;
            return go(a,node[now].r);
        }
    }
    
    void dfs(int k,int now)
    {
        if(node[now].id==k) return;
        if(k<node[now].id){
            printf("E");
            dfs(k,node[now].l);
        }
        else{
            printf("W");
            dfs(k,node[now].r);
        }
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        int T;cin>>T;
        while(T--){
            cin>>n;
            p=0;
            MS0(node);
            RI(a);
            node[++p]={a,0,0};
            int now=p;
            REP(i,2,n){
                RI(a);
                now=go(a,1);
                node[++p]={a,0,0};
                if(a<node[now].id) node[now].l=p;
                else node[now].r=p;
            }
            RI(q);
            while(q--){
                RI(k);
                dfs(k,1);
                printf("
    ");
            }
        }
        return 0;
    }
    View Code

    用数组模拟一下就好了,昨天一直调到现在,终于发现是go(a,1)写成go(a,now)了。。。

    这种错误很难发现,两种方法,一种是把代码写得尽量简洁清晰,然后一步步逐个检查每个部分,另一种就是重写。比赛的时候应该先调试找数据,没发现什么就不要交,应该逐步检查,如果没检查出来也不要交,应该重写一遍,然后确定没问题后交一下,如果再不过就暂时去看其它题。

    这场太悲剧了,上面几道题只过了签到,再加上队友的1002求联通分量的,本来该过7题的比赛居然只过了2题。。。。要是当时暂时放弃1010,去帮队友写1005就好了。。。比赛的时候自己前3个多小时一直在调1010换模板,后一个小时多1001卡到比赛结束。。。

    总的来说,下一场可不能这么混乱地卡题了。。。模板要提前准备好,然后要相信模板没问题,如果WA了一定是自己代码的问题。如果卡题了要先把那道题先放放,先去帮队友调题目或者帮队友写其它题,让队友看新题(这个因为我英语能力不怎么样),不能像这场这样一道题卡3个多小时。模拟题要写之前一定要想好思路,和队友先交流一下,再写,最好能够先想好坑点。

    该学的知识点都学到了,该过的题却没过,这是比赛中最忌讳的。如果说当时省赛是因为什么都不会打铁,不会离线并查集,不会线段树,不会数位dp,不会kmp,不会连通图,不会lca,不知道BSGS,但是,现在完全不一样了,我们学了并查集,离线,线段树,树状数组,数位dp,kmp,lca,后缀数组,中国剩余定理,树链剖分,连通图,网络流和二分图,状压dp,单调栈,同时又做了一些dp题。。。很多题我们都可以做的却没有在比赛中发挥出来,这不是知识点的问题,而是比赛经验的问题。比如今天这场,lucas和剩余定理学了,思路也出了,离线并查集也是,优先队列也是,模拟建树和后缀数组是没看,但并不是我们没时间看,而是比赛策略问题,卡题了。这些题知识点都学过,思路也出了,如果连这些都不能过的话还打什么区域赛。

    希望我们能在周末的网络赛之前能再训练两场保持状态,还有一定要帮队友把这场的题全补了。

    还有就是比赛的前一天一定不要熬夜,当时前一天自己半夜4点才睡。。。第二天碰上207机房那么冷的空调,又没吃早餐,头脑本来一片混乱,怎么可能写出模拟题。。。

    下一场的目标当然是抢名额,会有把我们和对面那些队拉开差距的比赛,但是这场如果我们发挥稳定不卡题的话,拉开差距? 并不能!

    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    汤姆大叔JavaCript系列10阅读笔记1
    界面设计
    html5 canvas store 和 restore 详解
    js 的上下文
    PHP实现大数以,做分隔符分隔
    Javascript可以兼容各浏览器的阻止默认行为发生的方法
    Javascript实现页面内元素添加滚动条
    $.getjson遇到的几个问题json返回数据中带有html标签的输出
    MYSQL的随机查询的实现方法
    jQuery插件:jqplot图表绘制插件详解
  • 原文地址:https://www.cnblogs.com/--560/p/4808094.html
Copyright © 2011-2022 走看看