Codeforces Round #261 (Div. 2) A,B,C,D,E

A. Pashmak and Garden

链接:http://codeforces.com/problemset/problem/459/A

大致题意:给你正方形的两个顶点输出正方形的另外两个顶点,需要注意的时候,这个正方形的边和x,y轴都是平行的(一开始没有注意到这个地方感觉这个题好难呀),并且所有的坐标都是整数。

思路:计算出给出的坐标的x方向的差值和y方向上的差值(注意取绝对值),如果有一个差值为零就说明给出的坐标在正方形的一条边上,如何差值不等输出-1,否则给出的坐标就应该在正方形的对角线上,剩下的就是算就行了没什么说的了~~~(ps.本人犯了sb错误,a题最后被卡掉了。。。)

code:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include<cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
#define INF 2000000000
using namespace std;
typedef long long ll;
const int MAX_E=400010;
const int MAX_N=1000;
const int MAX_T=30;
const double eps=1e-10;
int abc(int x)
{
    if(x<0) return -x;
    return x;
}
int main()
{
    int x1,y1,x2,y2;
    scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    int xx=abc(x2-x1),yy=abc(y2-y1);
    if(xx!=yy&&xx!=0&&yy!=0) printf("-1\n");
    else if(xx==0){
        printf("%d %d %d %d\n",x1+yy,y1,x2+yy,y2);
    }
    else if(yy==0){
        printf("%d %d %d %d\n",x1,y1+xx,x2,y2+xx);
    }
    else{
        printf("%d %d %d %d\n",x1,y2,x2,y1);
    }
    return 0;
}


B. Pashmak and Flowers

链接:http://codeforces.com/problemset/problem/459/B

大致题意:给你一个数列,让你求出的此数列的最大差值,并且输出达到此差值时的取法种数。

思路:直接最暴力的排序应该都能过,不知道为什么我一开始的暴力超时了,最后又优化了一个O(n)的方法。 在输入的时候不断更新一个数列的最大值和最小值,并且记录等于此值的数的个数,在更新完成之后如果发现,最大值和最小值相等,则输出0 (n*(n-1))/2,用这种情况成功hack一炮,否则就输出最大值-最小值 最大个数*最小个数

code:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include<cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
#define INF 2000000000
using namespace std;
typedef long long ll;
const int MAX_E=400010;
const int MAX_N=100010;
const int MAX_T=30;
const double eps=1e-10;

typedef long long ll;
int main()
{
    int n,t1=-INF,t2=INF,cnt1=0,cnt2=0,a;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&a);
        if(a==t1) cnt1++;
        else if(a>t1){
            t1=a;
            cnt1=1;
        }
        if(a==t2) cnt2++;
        else if(a<t2){
            t2=a;
            cnt2=1;
        }
    }
    if(t1==t2) printf("0 %lld\n",(ll)n*(n-1)/2);
    else printf("%d %lld\n",t1-t2,(ll)cnt1*cnt2);
    return 0;
}

C. Pashmak and Buses

链接:http://codeforces.com/problemset/problem/459/C

题意:给你n个人,k辆车,旅行d天,问有没有一种分配方案使得没有两个人这d天是一直在一起的,如果有输出任意一种可行方案,如果没有输出-1

思路:比赛时候一直没思路,比赛完也没有什么思路,后来看了解题报告说本质是构造n个d位k进制数马上就有思路了。

首先判断,是否存在解,d位k进制数最多有d^k个,所以如果n大于d^k则可以直接输出-1.

对于构造可行解我的方法是一开始将d位都设成0之后每次都将老数+1来获得这个新的k进制数,中间要模拟进位不过都是很简单的了~~

code:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include<cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
#define INF 2000000000
using namespace std;
typedef long long ll;
const int MAX_E=400010;
const int MAX_N=1010;
const int MAX_T=30;
const double eps=1e-10;
typedef long long ll;
int dd[MAX_N][MAX_N];  //dd[i][j] 表示第i个学生,第j天坐的车。
int cc[MAX_N];
bool judge(int n,int k,int d)
{
    ll mid=k;
    for(int i=1;i<=d;i++){
        if(mid>=n) return 1;
        mid*=k;
    }
    return 0;
}

int main()
{
    memset(cc,0,sizeof(cc));
    memset(dd,0,sizeof(dd));
    int n,k,d;
    scanf("%d%d%d",&n,&k,&d);
    bool flag=judge(n,k,d);
    if(!flag){
        printf("-1\n");
    }
    else{
        for(int i=1;i<=n;i++){
            for(int j=0;j<d;j++) dd[i][j]=cc[j];
            cc[d-1]++;
            for(int t=d-1;t>=0;t--){
                if(cc[t]>=k){
                    cc[t]%=k;
                    cc[t-1]++;
                }
            }
        }
        for(int i=0;i<d;i++){
            for(int j=1;j<=n;j++) printf("%d%c",dd[j][i]+1,j==n? '\n':' ');
        }
    }
    return 0;
}

D. Pashmak and Parmida's problem

链接:http://codeforces.com/problemset/problem/459/D

大致题意:给定了一个序列并定义了一个函数f(l,r,x)表示在区间[l,r]上和x相等的数的个数,题目问的是给定序列,求满足(1 ≤ i < j ≤ n) 并且 f(1, i, ai)> f(j, n, aj)

这样的i,j数对的对数。

思路:思考一会儿应该就能想到用树状数组来做,我们可以设f(1,i,ai)这个函数为f1,f(j,n,aj)这个函数为f2,然后处理出每个数的f1的值和f2的值,然后再用树状数组快速的计算出对于每一个f2满足条件的f1有多少个(值小于f1且位置在f1的前面,这个地方树状数组的应用有点像之前poj的马桶刷题 2299),注意要用到离散化来节省空间。

code:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include<cstdio>
#include <vector>
#include <cmath>
#include <algorithm>
#define INF 2000000000
using namespace std;
typedef long long ll;
const int MAX_E=400010;
const int MAX_N=1010;
const int MAX_T=30;
const double eps=1e-10;
typedef long long ll;
int dd[MAX_N][MAX_N];  //dd[i][j] 表示第i个学生,第j天坐的车。
int cc[MAX_N];
bool judge(int n,int k,int d)
{
    ll mid=k;
    for(int i=1;i<=d;i++){
        if(mid>=n) return 1;
        mid*=k;
    }
    return 0;
}

int main()
{
    memset(cc,0,sizeof(cc));
    memset(dd,0,sizeof(dd));
    int n,k,d;
    scanf("%d%d%d",&n,&k,&d);
    bool flag=judge(n,k,d);
    if(!flag){
        printf("-1\n");
    }
    else{
        for(int i=1;i<=n;i++){
            for(int j=0;j<d;j++) dd[i][j]=cc[j];
            cc[d-1]++;
            for(int t=d-1;t>=0;t--){
                if(cc[t]>=k){
                    cc[t]%=k;
                    cc[t-1]++;
                }
            }
        }
        for(int i=0;i<d;i++){
            for(int j=1;j<=n;j++) printf("%d%c",dd[j][i]+1,j==n? '\n':' ');
        }
    }
    return 0;
}

大神超短代码:

#pragma pack(1)
#include <cstdio>
#include <map>
using namespace std;
map<int,int> mp;
int a[1000000],bit[1000000],pr[1000000];//看成1e5错一回
long long ans;
int n;
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",a+i);
        pr[i]=mp[a[i]]++;
    }
    for(int i=n-1;i>-1;i--){
        for(int j=pr[i];j!=0;j-=(j&-j))ans+=bit[j];
        for(int j=mp[a[i]]-pr[i];j<n;j+=(j&-j)){bit[j]++;}
    }
    printf("%I64d\n",ans);
    return 0;
}

E. Pashmak and Graph

链接:http://codeforces.com/problemset/problem/459/E

大致题意:给出一个有向图,求一个最长的权值严格递增的路径长度。

思路:看到了题目上dp标签就想着用dp来做。之前想着用边dp来做,超时了,感觉可以改成节点dp来优化。dp[i]表示以第i个城市为结尾的满足题意的路径的最长长度,更新的时候将所有的边按照权值升序排序,再从第一条边开始更新,对于一条由s指向t的边mm,则有dp[t]=dp[s]+1(因为是从小到大取的边所以dp[s]的值一定是由小于等于mm的权值的边更新来的),但是这里面有一个问题是题目要求的边是严格递增的,也就是不能由权值相等的边来更新,这时我们就要选择权值小于更新dp[s]的边的边,所更新的dp[s]来更新当前的dp[t],这个时候我们就要记录一个有次大权值更新的dp值,同时也需要记录更新最大值的权值。

code:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include<cstdio>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
#define INF 2000000000
using namespace std;
typedef long long ll;
const int MAX_E=600010;
const int MAX_N=300010;
const int MAX_T=30;
const double eps=1e-10;
typedef long long ll;
int N,E;
struct nn
{
    int cost;
    int q1,q2;
}   dp[MAX_N];
struct eee
{
    int s,t,cost;
}   Es[MAX_E];

bool cmp(eee A,eee B)
{
    return A.cost<B.cost;
}

int main()
{
    scanf("%d%d",&N,&E);
    memset(dp,0,sizeof(dp));
    for(int i=0;i<E;i++){
        scanf("%d%d%d",&Es[i].s,&Es[i].t,&Es[i].cost);
    }
    sort(Es,Es+E,cmp);
    int ans=0;
    for(int i=0;i<E;i++){
        int ss=Es[i].s,tt=Es[i].t,cc=Es[i].cost;
        if(cc>dp[ss].cost){
            if(dp[tt].q1<dp[ss].q1+1){
                dp[tt].q2=dp[tt].q1;
                dp[tt].q1=dp[ss].q1+1;
                dp[tt].cost=cc;
            }
        }
        else{
            if(dp[tt].q1<dp[ss].q2+1){
                dp[tt].q2=dp[tt].q1;
                dp[tt].q1=dp[ss].q2+1;
                dp[tt].cost=cc;
            }
        }
        ans=max(dp[tt].q1,ans);
    }
    printf("%d\n",ans);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值