zoukankan      html  css  js  c++  java
  • 2013 成都邀请赛

               今年又要打邀请赛了,前段时间做比赛都被虐的够呛,感觉不会再爱了。。。所以挂了下去年的成都邀请赛的题目。发现简单题还是能切上几道的,可是难题就无能为力了。。。阿门,还是水平差得远啊。。。(ps:近期感觉状态不佳,依靠了队友神勇的发挥。。。

             

    Current Time: 2014-05-15 08:43:24 Contest Type: Public
    Start Time: 2014-05-14 15:10:00 Contest Status: Ended
    End Time: 2014-05-14 20:10:00 Manager: ok_again

               A,一如既往的最签到的题目。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define eps 1e-8
    #define PI acos(-1.0)
    #define maxn 22000
    #define INF 0x3f3f3f3f
    #define E exp(double(1))
    #define CLR(a, b) memset(a, b, sizeof(a))
    using namespace std;
    
    #ifdef __int64
        typedef __int64 LL;
    #else
        typedef long long LL;
    #endif
    
    int main(){
        int i,j,k,a,b;
        int _,cas=1;
        cin>>_;
        while(_--){
            cin>>a;
            a/=10;
            printf("Case #%d:
    ",cas++);
            puts("*------------*");
            b=a;
            a=10-a;
            while(a--){
                puts("|............|");
            }
            while(b--){
                puts("|------------|");
            }
            puts("*------------*");
        }
        return 0;
    }

               B题找的是最长的距离最短,是一个下凹的图形,直接三分就可以。。

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    const double eps=1e-8;
    struct point{
        double x,y;
        point(double a=0,double b=0){
            x=a,y=b;
        }
        point operator+(const point &a){
            return point(a.x+x,a.y+y);
        }
        point operator*(const double &a){
            return point(x*a,y*a);
        }
        void input(){
            scanf("%lf%lf",&x,&y);
        }
    }p[500],vp[500],tmp[500];
    int n;
    double dist(point a,point b){
        double x=a.x-b.x;
        double y=a.y-b.y;
        return sqrt(x*x+y*y);
    }
    double calc(double t){
        for(int i=0;i<n;i++) tmp[i]=p[i]+vp[i]*t;
        double res=-1;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++) res=max(res,dist(tmp[i],tmp[j]));
        }
        return res;
    }
    int main(){
        int t;
        scanf("%d",&t);
        for(int cas=1;cas<=t;cas++){
            scanf("%d",&n);
            for(int i=0;i<n;i++){
                p[i].input(),vp[i].input();
            }
            double l=0,r=1e20,mid,midmid;
            double ans=0;
            while(l+eps<r){
                mid=(l+r)/2;
                midmid=(mid+r)/2;
                double mid_=calc(mid);
                double midmid_=calc(midmid);
                if(mid_<midmid_){
                    r=midmid;ans=mid_;
                }
                else l=mid;
            }
            printf("Case #%d: ",cas);
            printf("%.2f %.2f
    ",l,ans);
        }
    }

               C题好像能够用LCA,保存6个值,各自是该区间的最长连续上升序列长度,左右端点连续上升序列长度,和分别得下降序列长度,便于查询时衔接用。。。比赛的时候想到了,可是没敲。。。所以这题代码就不给了。。。

                D题好题线段树+dp+单调性,比赛的时候剩余时间不多了,没怎么想到正解。。。后来看了下大家用的是线段树,自己想了想,的确能够用线段树维护。。。当时就哭了。线段树中维护的是长度为L的那一段中,高度区间中dp[i]-h[i]的值(保存这个是由于,那个递推式,应该非常明显能看出来),然后就是怎么往树中加点和删点了,明显,同一高度的假设后面出现的val值比掐面出现的val值还要大的话,前面哪一个肯定是无用的,所以我们须要维护每一个高度整体单调递减,然后删除的时候推断一下当前删除点是否在树中就能够了。。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define eps 1e-7
    #define PI acos(-1.0)
    #define inf 0x3f3f3f3f
    #define E exp(double(1))
    #define CLR(a, b) memset(a, b, sizeof(a))
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    using namespace std;
    
    #ifdef __int64
    typedef __int64 LL;
    #else
    typedef long long LL;
    #endif
    
    const int maxn = 222222;
    
    LL MAX[maxn<<2];
    int fir[maxn], nxt[maxn], h[maxn], pre[maxn], last[maxn];
    
    void PushUP(int rt)
    {
        MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]);
    }
    void update(int p,LL sc,int l,int r,int rt)
    {
        if (l == r)
        {
            MAX[rt] = sc;
            return ;
        }
        int m = (l + r) >> 1;
        if (p <= m) update(p , sc , lson);
        else update(p , sc , rson);
        PushUP(rt);
    }
    
    LL query(int L,int R,int l,int r,int rt)
    {
        if (L <= l && r <= R)
        {
            return MAX[rt];
        }
        int m = (l + r) >> 1;
        LL ret = -5;
        if (L <= m) ret = max(ret , query(L , R , lson));
        if (R > m) ret = max(ret , query(L , R , rson));
        return ret;
    }
    
    LL dp[maxn];
    
    void work(int cas)
    {
        int n, l;
        scanf("%d%d", &n, &l);
        for(int i = 1; i <= n; i ++)
        {
            scanf("%d", &h[i]);
        }
        CLR(MAX, -1);CLR(dp, -1);
        CLR(pre, -1);
        printf("Case #%d: ", cas);
        for(int i = 1; i <= n; i ++)
        {
            LL tmp;
            if(h[i] == 1) tmp = -1;
            else tmp = query(1, h[i] - 1, 1, 100000, 1);
            if(tmp == -1 && i > l)
            {
                goto ed;
            }
            if(tmp == -1) tmp = 0;
            tmp += 1ll*h[i]*h[i] - h[i];
            dp[i] = tmp;
            int j;
            for(j = pre[h[i]]; j != -1; j = last[j])
            {
                if(dp[j] > dp[i]) break;
            }
            if(j == -1)
            {
                pre[h[i]] = i;
                fir[h[i]] = i;
                last[i] = -1;
                update(h[i], dp[i], 1, 100000, 1);
            }
            else
            {
                pre[h[i]] = i;
                nxt[j] = i;
                last[i] = j;
            }
            if(i <= l) continue;
            ed:;
            if(fir[h[i - l]] == i - l)
            {
                if(pre[h[i - l]] == fir[h[i - l]])
                {
                    pre[h[i - l]] = -1;
                    update(h[i - l], -1, 1, 100000, 1);
                }
                else
                {
                    fir[h[i - l]] = nxt[fir[h[i - l]]];
                    update(h[i - l], dp[fir[h[i - l]]], 1, 100000, 1);
                }
            }
        }
        if(dp[n] == -1) puts("No solution");
        else printf("%I64d
    ", dp[n] + h[n]);
    }
    
    int main()
    {
        int T, cas = 1;
        scanf("%d", &T);
        while(T --)
        {
            work(cas ++);
        }
    }
    
    /*
    555
    5 1
    24 5452 3542 452 14
    */

                  E题,这道题队友兴冲冲的就上去敲了,表示全然不知道题目。。。只是还是把代码附上吧。

    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    const double eps=1e-8;
    struct point{
        double x,y;
        point(double a=0,double b=0){
            x=a,y=b;
        }
        void input(){
            scanf("%lf%lf",&x,&y);
        }
    }p[4],now,ori;
    double r;
    double dist(point a,point b){
        double x=a.x-b.x;
        double y=a.y-b.y;
        return sqrt(x*x+y*y);
    }
    point getpoint(point a,point b,point c){
        double bx=b.x-a.x,by=b.y-a.y;
        double cx=c.x-a.x,cy=c.y-a.y;
        double d=2*(bx*cy-by*cx);
        double x=(cy*(bx*bx+by*by)-by*(cx*cx+cy*cy))/d+a.x;
        double y=(bx*(cx*cx+cy*cy)-cx*(bx*bx+by*by))/d+a.y;
        return point(x,y);
    }
    void MiniOver(){
        ori=p[0];r=0;
        for(int i=1;i<3;i++){
            if(dist(ori,p[i])+eps>r){
                ori=p[i],r=0;
                for(int j=0;j<i;j++)
                    if(dist(ori,p[j])+eps>r){
                        ori.x=(p[i].x+p[j].x)/2;
                        ori.y=(p[i].y+p[j].y)/2;
                        r=dist(ori,p[j]);
                        for(int k=0;k<j;k++)
                            if(dist(ori,p[k])+eps>r){
                                ori=getpoint(p[i],p[j],p[k]);
                                r=dist(ori,p[k]);
                            }
                    }
            }
        }
    }
    int main(){
        int t;
        scanf("%d",&t);
        for(int i=1;i<=t;i++){
            for(int j=0;j<3;j++) p[j].input();
            MiniOver();
            now.input();
            printf("Case #%d: ",i);
            if(dist(now,ori)<=r) puts("Danger");
            else puts("Safe");
        }
    }

               G题是一道简单的数位dp。忘了0的情况。。。检查了n久,罪过啊。dp[i][j]表示长度为i位,余数为j有多少种数(包含前导零)。然后就显然了。。。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define eps 1e-7
    #define PI acos(-1.0)
    #define maxn 300
    #define INF 0x3f3f3f3f
    #define E exp(double(1))
    #define CLR(a, b) memset(a, b, sizeof(a))
    using namespace std;
    
    #ifdef __int64
    typedef __int64 LL;
    #else
    typedef long long LL;
    #endif
    
    LL dp[20][15];
    
    void init()
    {
        CLR(dp, 0);
        dp[0][0] = 1;
        for(int i = 1; i < 20; i ++)
        {
            for(int j = 0; j < 10; j ++)
            {
                for(int k = 0; k < 10; k ++)
                {
                    dp[i][(j + k) % 10] += dp[i - 1][j];
                }
            }
        }
    }
    
    int c[25];
    
    LL cal(LL a)
    {
        int len = 0;
        while(a)
        {
            c[len ++] = a % 10;
            a /= 10;
        }
        LL ret = 0;
        int sum = 0;
        for(int i = len - 1; i >= 0; i --)
        {
            if(i) for(int j = 1; j < 10; j ++)
            {
                ret += dp[i - 1][(10 - j)%10];
            }
            for(int j = 0; j < c[i]; j ++)
            {
                if(i == len - 1 && j == 0)
                {
                    sum = (sum + 1) % 10;
                    continue;
                }
                ret += dp[i][(10 - sum) % 10];
                sum = (sum + 1) % 10;
            }
        }
        return ret;
    }
    
    int main()
    {
        int T, cas = 1;
        init();
        scanf("%d", &T);
        while(T --)
        {
            LL a, b;
            scanf("%I64d%I64d", &a, &b);
            printf("Case #%d: ", cas ++);
            LL ans = cal(b + 1) - cal(a);
            if(a == 0) ans ++;
            printf("%I64d
    ", ans);
        }
    }

                H题,贪心一下就好了。最左边上下两点可定要连线,然后分别捡短的线连就能够了。。。(正确性不可证,画了下图感觉挺对的。。)

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define eps 1e-7
    #define PI acos(-1.0)
    #define maxn 100100
    #define inf 0x3f3f3f3f
    #define E exp(double(1))
    #define CLR(a, b) memset(a, b, sizeof(a))
    using namespace std;
    
    #ifdef __int64
        typedef __int64 LL;
    #else
        typedef long long LL;
    #endif
    
    int c[maxn], d[maxn], ca;
    
    double len(int i, int j)
    {
        return sqrt(1.0*ca*ca + 1.0*(c[i] - d[j])*(c[i] - d[j]));
    }
    
    int main()
    {
        int T, cas = 1;
        int n, m, a, b;
        scanf("%d", &T);
        while(T --)
        {
            scanf("%d%d", &a, &b);
            scanf("%d%d", &n, &m);
            for(int i = 0; i < n; i ++)
            {
                scanf("%d", &c[i]);
            }
            for(int i = 0; i < m; i ++)
            {
                scanf("%d", &d[i]);
            }
            int y1, y2; ca = abs(a - b); double ans = 0.0;
            ans += len(0, 0);
            for(y1 = 0, y2 = 0; y1 < n && y2 < m;)
            {
                double tmp1 = 1e20, tmp2 = 1e20;
                if(y1 == n - 1 && y2 == m - 1) break;
                if(y1 < n - 1) tmp1 = len(y1+1, y2);
                if(y2 < m - 1) tmp2 = len(y1, y2+1);
                if(tmp1 < tmp2) ans += tmp1, y1 ++;
                else ans += tmp2, y2 ++;
            }
            printf("Case #%d: %.2f
    ", cas ++, ans);
        }
    }

                  J题想了n久才想到正解。。。本来想敲spfa的,队友说他先前敲的dij还在,就让他上去改了。。。大概就是我们须要把每一层都都当做一个节点,这种话第i层的点是能够更新第i+1层的全部点的,我们仅仅需把代表第i+1层的点更新了就能够了。。层节点代表的整层的信息。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define eps 1e-7
    #define PI acos(-1.0)
    #define inf 0x3f3f3f3f
    #define E exp(double(1))
    #define CLR(a, b) memset(a, b, sizeof(a))
    using namespace std;
    
    #ifdef __int64
    typedef __int64 LL;
    #else
    typedef long long LL;
    #endif
    
    #define maxn 201000
    #define maxe 601000
    
    struct Edge{
        int from,to,dis,next;
    }edge[maxe];
    int head[maxn];
    int n,m,c,cnt;
    void add(int q,int h,int len){
        edge[cnt].from=q;
        edge[cnt].to=h;
        edge[cnt].dis=len;
        edge[cnt].next=head[q];
        head[q]=cnt;
        cnt++;
    }
    void init(){
        cnt=0;
        memset(head,-1,sizeof head);
    }
    
    int belong[maxn];
    vector<int>v[maxn];
    
    struct node{
        int u,c;
        node(int u,int c):u(u),c(c){};
        node(){};
        friend bool operator <(node a,node b){
            return a.c>b.c;
        }
    }tmp;
    int can[maxn];
    int dis[maxn];
    bool used[maxn];
    priority_queue<node>q;
    void dij(int s,int ttt){
        int t,u,w;
        while(!q.empty())q.pop();
        memset(used,0,sizeof used);
        memset(dis,inf,sizeof dis);
        tmp=node(s,0);
        dis[s]=0;
        q.push(tmp);
        if(belong[s]+1<=2*n && can[belong[s]+1]){
            tmp=node(belong[s]+1,c);
            dis[belong[s]+1]=c;
            q.push(tmp);
        }
        if(belong[s]-1>n && can[belong[s]-1]){
            tmp=node(belong[s]-1,c);
            dis[belong[s]-1]=c;
            q.push(tmp);
        }
        while(!q.empty()){
            tmp=q.top();
            q.pop();
            t=tmp.u;
            if(used[t])continue;
            else used[t]=true;
            for(int i=head[t];i!=-1;i=edge[i].next){
                u=edge[i].to;
                w=edge[i].dis;
                if(used[u])continue;
                if(dis[t]+w<dis[u]){
                    dis[u]=dis[t]+w;
                    q.push(node(u,dis[u]));
                    if(u<=n){
                        if(belong[u]<=n*2 && can[belong[u]+1] && dis[t]+w+c < dis[ belong[u]+1 ]){
                            dis[ belong[u]+1 ]=dis[t]+w+c;
                            q.push(node(belong[u]+1,dis[t]+w+c));
                        }
                        if(belong[u]-1>n && can[belong[u]-1] && dis[t]+w+c < dis[ belong[u]-1 ]){
                            dis[ belong[u]-1 ]=dis[t]+w+c;
                            q.push(node(belong[u]-1,dis[t]+w+c));
                        }
                    }
                }
            }
            if(t>n){
                if(t<=n*2 && can[t+1] && dis[t]+c < dis[ t+1 ]){
                    dis[ t+1 ]=dis[t]+c;
                    q.push(node(t+1,dis[t]+c));
                }
                if(t-1>n && can[t-1] && dis[t]+c < dis[ t-1 ]){
                    dis[ t-1 ]=dis[t]+c;
                    q.push(node(t-1,dis[t]+c));
                }
            }
        }
    }
    
    inline int get_int(){
        int ret=0;
        char c;
        while(!isdigit(c=getchar()));
        do{
            ret =(ret<<3)+(ret<<1)+c-'0';
        }while(isdigit(c=getchar()));
        return ret;
    }
    
    
    
    int main(){
        int _,cas=1,q,h,cost;
        cin>>_;
        while(_--){
            n=get_int(),m=get_int(),c=get_int();
            init();
            memset(can,0,sizeof can);
            for(int i=1;i<=n;i++){
                belong[i]=get_int();
                belong[i]+=n;
                can[belong[i]]=1;
            }
    
            for(int i=0;i<m;i++){
                q=get_int(),h=get_int(),cost=get_int();
                add(belong[q],h,cost);
                add(belong[h],q,cost);
                add(q,h,cost);
                add(h,q,cost);
            }
    
            dij(1,n);
            printf("Case #%d: ",cas++);
    
            int ans=min(dis[belong[n]],dis[n]);
    
    
            if(ans==inf){
                puts("-1");
            }else{
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    

                K题是一道计数题?没看题。。。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define eps 1e-8
    #define PI acos(-1.0)
    #define maxn 2200000
    #define INF 0x3f3f3f3f
    #define E exp(double(1))
    #define CLR(a, b) memset(a, b, sizeof(a))
    using namespace std;
    
    #ifdef __int64
        typedef __int64 LL;
    #else
        typedef long long LL;
    #endif
    
    char s[maxn];
    int c1[11];
    int cp1[11];
    int cp2[11];
    int c2[11];
    int x1,x2;
    int cnt[11];
    int ctt[11];
    
    int gethead(){
        for(int i=9;i>=0;i--){
            for(int j=0;j<=9;j++){
                int tt = (i-j);
                if(tt<0)tt+=10;
                if(j==0||tt==0)continue;
                if(c1[j]&&c2[tt]){
                   return i;
                }
            }
        }
    }
    
    
    void getnext(){
    
        for(int sum=9;sum>=0;sum--){
            for(int a=0;a<=9;a++){
                int b = (sum-a);
                if(b<0)b+=10;
                int cc = min(c1[a],c2[b]);
                c1[a]-=cc;
                c2[b]-=cc;
                cnt[sum]+=cc;
            }
        }
    
        bool ok;
        for(int i=9;i>=0;i--){
            if(cnt[i]==ctt[i])continue;
            if(cnt[i]<ctt[i])ok=false;
            else ok=true;
            break;
        }
        if(ok){
            for(int i=0;i<=9;i++){
                ctt[i]=cnt[i];
            }
        }
    }
    
    
    int main(){
        int _,cas=1;
        cin>>_;
        while(_--){
            memset(c1,0,sizeof c1);
            memset(c2,0,sizeof c2);
            memset(cnt,0,sizeof cnt);
            memset(ctt,0,sizeof ctt);
            scanf("%s",s);
            for(int i=0;s[i];i++)c1[s[i]-'0']++;
            scanf("%s",s);
            for(int i=0;s[i];i++)c2[s[i]-'0']++;
            int h = gethead();
    
            for(int i=0;i<=9;i++){
                cp1[i]=c1[i];
                cp2[i]=c2[i];
            }
    
            for(int i=0;i<=9;i++){
                for(int j=0;j<=9;j++){
                    c1[j]=cp1[j];
                    c2[j]=cp2[j];
                }
                int tt = (h-i);
                if(tt<0)tt+=10;
                if(i==0||tt==0)continue;
                if(c1[i]&&c2[tt]){
                    c1[i]--;
                    c2[tt]--;
                    memset(cnt,0,sizeof cnt);
                    getnext();
                }
            }
    
            bool ok=false;
            if(h!=0)ok=true;
            printf("Case #%d: ",cas++);
            if(h!=0)printf("%d",h);
            for(int i=9;i>=1;i--){
                while(ctt[i]--){
                    printf("%d",i);
                    ok=true;
                }
            }
            if(ok){
                 while(ctt[0]--){
                    printf("%d",0);
                }
            }else{
                printf("0");
            }
            puts("");
        }
        return 0;
    }
    

                  L题,第二签到题。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define eps 1e-8
    #define PI acos(-1.0)
    #define maxn 220000
    #define INF 0x3f3f3f3f
    #define E exp(double(1))
    #define CLR(a, b) memset(a, b, sizeof(a))
    using namespace std;
    
    #ifdef __int64
        typedef __int64 LL;
    #else
        typedef long long LL;
    #endif
    
    int s[maxn];
    
    int main(){
        int i,j,k,n,b;
        int _,cas=1;
        cin>>_;
        while(_--){
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d",&s[i]);
            }
            b=-1;
            for(int i=2;i<=n;i++){
                if(s[i]-s[i-1]!=1){
                    b=i;
                }
                if(~b)break;
            }
            if(b==-1)b=1;
            printf("Case #%d: %d
    ",cas++,b);
        }
        return 0;
    }


  • 相关阅读:
    逻辑运算(二)
    Rust基础类型
    Rust简单demo
    逻辑基础(一)
    webpack配置typescript项目
    Go并发原理
    JS实现取任意类型的数组交集并集方法的思考
    JS 可逆加密的一种实现
    所有中文复姓
    将中文姓名转为拼音英文名的一种实现
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/3806210.html
Copyright © 2011-2022 走看看