Codeforces Round #367 (Div. 2) A~E

来源:互联网 发布:信息管理与网络维护 编辑:程序博客网 时间:2024/05/22 00:08

A. Beru-taxi
水题

#include<bits/stdc++.h>using namespace std;int main(){    double x,y;    while(cin>>x>>y){        int n;cin>>n;        double ans=99999999.0;        for(int i=0;i<n;i++){            double a,b,v;cin>>a>>b>>v;            ans=min(ans,sqrt((x-a)*(x-a)+(y-b)*(y-b))/v);        }        printf("%.10f\n",ans);    }}

B. Interesting drink
题意:q(1<=q=100000)次询问某个数在n(1<=n<=100000)个数里比他小于等于的位置。
后话:那天晚上,我很困,看错题意看成求某个数在n个序列里,比他小而且连续的序列最长长度是。然后没想出来,睡着了….然后这场就跪了…

思路:排序(nlgn)后二分(q*lgn).

#include<bits/stdc++.h>using namespace std;const int N=1e5+10;int a[N];int main(){    int n;    while(~scanf("%d",&n)){        for(int i=0;i<n;i++) scanf("%d",&a[i]);        int q;scanf("%d",&q);        sort(a,a+n);        while(q--){            int x;scanf("%d",&x);            int ans=upper_bound(a,a+n,x)-a;            printf("%d\n",ans);        }    }}

C. Hard problem
题意:有n个字符串,对于每个串s[i]有一个翻转的功能,花费不等的c[i],问怎么样翻转使所有串按照字典序不递减的顺序。
思路:对每个串考虑就是翻不翻,只有两个状态,很水的动态规划,设dp[n][2],dp[i][0]表示从第一个串当前第i个串不翻转的耗费,dp[i][1]表示从第一个串到当前i串翻转的耗费。
转移方程从当前串与上一个串字典序大小关系进行转移。

#include<bits/stdc++.h>using namespace std;const int maxn=100000+10;typedef long long ll;ll dp[maxn][2],c[maxn];string s[maxn],rs[maxn];const ll inf=0x7fffffffffff;int main(){    int n;    while(~scanf("%d",&n)){       for(int i=1;i<=n;i++) scanf("%I64d",&c[i]);       for(int i=0;i<=n;i++){         dp[i][0]=inf;         dp[i][1]=inf;       }       dp[0][0]=0;dp[0][1]=0;       for(int i=1;i<=n;i++){         cin>>s[i];rs[i]=s[i];         reverse(rs[i].begin(),rs[i].end());         if(s[i]>=s[i-1])  dp[i][0]=min(dp[i][0],dp[i-1][0]);         if(s[i]>=rs[i-1]) dp[i][0]=min(dp[i][0],dp[i-1][1]);         if(rs[i]>=s[i-1]) dp[i][1]=min(dp[i][1],dp[i-1][0]+c[i]);         if(rs[i]>=rs[i-1]) dp[i][1]=min(dp[i][1],dp[i-1][1]+c[i]);       }       ll ans=min(dp[n][0],dp[n][1]);       if(ans==inf) printf("-1\n");       else printf("%I64d\n",ans);    }}

D. Vasiliy’s Multiset
题意:进行n次操作 首先0 在集合内
+ 表示将 x加入集合内
- 表示将x从集合里删除
? 表示查询x与集合内的数的 异或的最大值
思路:异或最大值,实际上就在集合里找与x二进制位1出现位置不同最多的那个数。
我们可以把每个数二进制化放在一棵树里,然后查找位置1不同最多的那个数。这题就是类是一个字典树的写法。每层就是0,1.思路很清晰。

#include<bits/stdc++.h>using namespace std;struct node{   int one,zero,cnt1,cnt0;}a[10000000+10];int t;int main(){    int n;    while(~scanf("%d",&n)){        memset(a,0,sizeof(a));        t=1;        for(int i=0;i<=n;i++){            char c;int x;            if(i==0) { c='+';x=0;}            else scanf(" %c %d",&c,&x);            if(c=='+'){                int bit[32],v=1;                for(int i=0;i<32;i++){                    bit[i]=x%2;x/=2;                }                for(int i=31;i>=0;i--){                    if(bit[i]==1){                        a[v].cnt1++;                        if(a[v].one==0) a[v].one=++t;                        v=a[v].one;                    }                    else{                        a[v].cnt0++;                        if(a[v].zero==0) a[v].zero=++t;                        v=a[v].zero;                    }                }            }            else if(c=='-'){                int bit[32],v=1;                for(int i=0;i<32;i++){                    bit[i]=x%2;x/=2;                }                for(int i=31;i>=0;i--){                    if(bit[i]==1){                        a[v].cnt1--;                        v=a[v].one;                    }                    else{                        a[v].cnt0--;                        v=a[v].zero;                    }                }            }            else if(c=='?'){                int ans=0;                int bit[32],v=1;                for(int i=0;i<32;i++){                    bit[i]=x%2;x/=2;                }                for(int i=31;i>=0;i--){                    if(bit[i]==1){                        if(a[v].cnt0>0){                            ans+=(1<<i);                            v=a[v].zero;                        }                        else v=a[v].one;                    }                    else{                        if(a[v].cnt1>0){                            ans+=(1<<i);                            v=a[v].one;                        }                        else v=a[v].zero;                    }                }                printf("%d\n",ans);            }        }    }}

E. Working routine
题意:在一个矩阵(1000*1000)里q(1<=q<=10000)次交换两个不相交小矩阵,怎么模拟时间复杂度最低?
思路:思考交换两个矩阵相对于每个点来说,只有矩阵的边周围的点关系变换了,中间的点四周的点并没有变化呢。所以最简单的做法就是存每个点四周点事什么,实际只用存右边,下边点是什么。然后转换的过程只用转换小矩阵四条边。O(q*(n+m))时间复杂度

#include<bits/stdc++.h>using namespace std;const int maxn=1050;struct node{   int v;   node *right,*down;}s[maxn][maxn];int main(){     int n,m,q;     while(~scanf("%d %d %d",&n,&m,&q)){         for(int i=1;i<=n;i++){            for(int j=1;j<=m;j++){                scanf("%d",&s[i][j].v);            }         }         for(int i=0;i<=n;i++){            for(int j=0;j<=m;j++){                s[i][j].right=&s[i][j+1];                s[i][j].down=&s[i+1][j];            }         }         while(q--){            int a,b,c,d,h,w;            scanf("%d %d %d %d %d %d",&a,&b,&c,&d,&h,&w);            node *nowu[2]={&s[a-1][0],&s[c-1][0]};            node *nowd[2]={&s[a-1+h][0],&s[c-1+h][0]};            for(int i=1;i<=b;i++){                nowu[0]=nowu[0]->right;                nowd[0]=nowd[0]->right;            }            for(int i=1;i<=d;i++){                nowu[1]=nowu[1]->right;                nowd[1]=nowd[1]->right;            }            node *nowl[2]={&s[0][b-1],&s[0][d-1]};            node *nowr[2]={&s[0][b-1+w],&s[0][d-1+w]};            for(int i=1;i<=a;i++){                nowl[0]=nowl[0]->down;                nowr[0]=nowr[0]->down;            }            for(int i=1;i<=c;i++){                nowl[1]=nowl[1]->down;                nowr[1]=nowr[1]->down;            }            for(int i=1;i<=h;i++){                swap(nowl[0]->right,nowl[1]->right);                nowl[0]=nowl[0]->down;nowl[1]=nowl[1]->down;                swap(nowr[0]->right,nowr[1]->right);                nowr[0]=nowr[0]->down;nowr[1]=nowr[1]->down;            }            for(int i=1;i<=w;i++){                swap(nowu[0]->down,nowu[1]->down);                nowu[0]=nowu[0]->right;nowu[1]=nowu[1]->right;                swap(nowd[0]->down,nowd[1]->down);                nowd[0]=nowd[0]->right;nowd[1]=nowd[1]->right;            }         }         for(int i=1;i<=n;i++){            node *now=&s[i][0];            for(int j=1;j<=m;j++){                now=now->right;                printf("%d ",now->v);            }            printf("\n");         }     }}
0 0
原创粉丝点击