Codeforces Round #365 Div.2

  血崩,做了俩小时只过了一道题,低级错误疯狂的犯。幸好不知道为什么貌似没算分,不然rating要爆炸。

  A:呵呵

#include<stdio.h>
#include<stdlib.h>
int main()
{
    //freopen("input.txt","r",stdin) ;
    int N;
    scanf("%d",&N);
    int x=0,y=0;
    for (int i=1;i<=N;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        if (a>b) x++;
        if (a<b) y++;
    }
    if (x>y) printf("Mishka
");
    else if (x<y) printf("Chris
");
    else printf("Friendship is magic!^^
");
    //fclose(stdin);
    return 0;
}
View Code

  B:先算最外边的环路,然后算capital到非capital,再算capital到capital。注意算后两步的时候要确定两个点是否相邻,如果相邻则不必计算。capital到capital的计算结果要除以2。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
using namespace std;
int ABS(int x)
{
    if (x>0) return x;
    else return -1*x;
}
bool v[150000];
int c[150000],p[150000];
int main()
{
    int N,K;
    while (cin>>N>>K)
    {
        memset(v,false,sizeof(v));
        for (int i=1;i<=N;i++) cin>>c[i];
        for (int i=1;i<=K;i++) 
        {
            cin>>p[i];
            v[p[i]]=true;
        }
        unsigned long long ans=0;
        for (int i=1;i<N;i++) ans+=c[i]*c[i+1];
        if (N!=1) ans+=c[N]*c[1];
        long long sum1=0,sum2=0;
        for (int i=1;i<=N;i++)
        {
            if (v[i]) sum1+=c[i];
            else sum2+=c[i];
        }
        for (int i=1;i<=K;i++)
        {
            int l=p[i]-1,r=p[i]+1;
            if (l==0) l=N;
            if (r==N+1) r=1;
            long long tmp=sum2;
            if (!v[l]) tmp-=c[l];
            if (!v[r]) tmp-=c[r];
            ans+=tmp*c[p[i]];
        }
        long long add=0;
        for (int i=1;i<=K;i++)
        {
            int l=p[i]-1,r=p[i]+1;
            if (l==0) l=N;
            if (r==N+1) r=1;
            long long tmp=sum1;
            tmp-=c[p[i]];
            if (v[l]) tmp-=c[l];
            if (v[r]) tmp-=c[r];
            add+=tmp*c[p[i]];
        }
        ans+=add/2;
        cout<<ans<<endl;
    }
    return 0;
}
View Code

  C:可以想象成车子不动,人具有恒定的水平方向分速度v,竖直方向分速度为0~u。只需使人的位移线与多边形不相交就等价于使车撞不到人。人要避开车子有两种方式,一种是曲线位于多边形上方,这种情况下人可以直接从0时刻开始以最高速度通过。条件是多边形所有顶点与原点的斜率小于u/v。否则,曲线应从多边形下方通过。首先找到到原点斜率最小的一个顶点,如果这个点到原点的斜率大于等于u/v,则人也可以最高速度直接通过。否则人先走到这个点,然后计算逆时针的下一个顶点到这个点的斜率,如果斜率比当前的斜率大,则人可以加速,并以相应的速度移动到与下一个点横坐标相同的位置,直到斜率超过最大斜率或斜率小于0,则剩余路程直接以最大速度通过。

#include<stdio.h>
#include<stdlib.h>
double ABS(double x)
{
    if (x>0) return x;
    else return -1*x;
}
double xl(double x1,double y1,double x2,double y2)
{
    if (ABS(x2-x1)<1e-10) return 1e15;
    return (y2-y1)/(x2-x1);
}
double x[12000],y[12000];
int main()
{
    int N;
    double w,v,u;
    while (scanf("%d%lf%lf%lf",&N,&w,&v,&u)!=EOF)
    {
        bool neg=false;
        for (int i=1;i<=N;i++) 
        {
            scanf("%lf%lf",&x[i],&y[i]);
            if (x[i]<=0) neg=true;
        }
        double ans=0;
        double maxxl=1e-15,minxl=1e15;
        int maxp,minp;
        for (int i=1;i<=N;i++)
        {
            double tmp=xl(0,0,x[i],y[i]);
            if (tmp>maxxl)
            {
                maxxl=tmp;
                maxp=i;
            }
            if (tmp<minxl && x[i]>0)
            {
                minxl=tmp;
                minp=i;
            }
        }
        double stdxl=u/v;
        if ((stdxl>=maxxl && neg==false) || minxl>stdxl)
        {
            ans=w/u;
            printf("%.8lf
",ans);
            return 0;
        }
        int p=minp;
        double curxl=minxl,cx=x[p],cy=y[p];
        ans=x[p]/v;
        while (curxl<stdxl)
        {
            p++;
            if (p==(N+1)) p=1;
            double tmpx=xl(cx,cy,x[p],y[p]);
            if (tmpx<0)
            {
                ans+=(w-cy)/u;
                printf("%.8lf
",ans);
                return 0;
                break;
            }
            if (tmpx>stdxl) tmpx=stdxl;
            curxl=tmpx;
            ans+=(x[p]-cx)/v;
            cy+=((x[p]-cx)*curxl);
            cx=x[p];
        }
        if (cy<w) ans+=(w-cy)/u;
        printf("%.8lf
",ans);
    }
    return 0;
}
View Code

  D:由于异或自身的结果为0,所以从l到r区间内所有数的异或和等于其中出现奇数次的数的异或和。为了求出出现偶数次数的数的异或和,只需将所有数的异或和再异或上l到r内所有出现过的数的异或和,就可以将本来出现偶数次数的变为奇数次,而奇数次则变为偶数次,得到所求答案。将所有询问按r排序,用数组f[x]保存从1到x所有出现过的数的异或和。当一个数再次出现时,以最新的位置为准,从而使f[r]^f[l-1]的值即为从l到r出现的所有种类数的异或和。

#include <map>  
#include <set>  
#include <cmath>  
#include <queue>  
#include <bitset>  
#include <math.h>  
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <cstring>  
#include <iostream>  
#include <algorithm>
using namespace std;
struct node
{
    int l,r,id;
    bool operator < (const node a)
    {
        return r<a.r;
    }
}q[1010000];
map<int,int> M;
int N,a[1010000],f[1010000],pre[1010000],xo[1010000],ans[1010000];
void add(int x,int y)
{
    for (;x<=N;x+=x&-x) f[x]^=y;
}
int get(int x)
{
    int ret=0;
    for (;x;x-=x&-x) ret^=f[x];
    return ret;
}
int main()
{
    int i,k,m;
    scanf("%d",&N);
    for (i=1;i<=N;i++)
    {
        scanf("%d",&a[i]);
        xo[i]=xo[i-1]^a[i];
    }
    for (i=1;i<=N;i++)
    {
        pre[i]=M[a[i]];
        M[a[i]]=i;
    }
    scanf("%d",&m);
    for (i=1;i<=m;i++) 
    {
        scanf("%d%d",&q[i].l,&q[i].r);
        q[i].id=i;
    }
    sort(q+1,q+m+1);
    for (k=1,i=1;i<=m;i++)
    {
        for (;k<=N&&k<=q[i].r;k++)
        {
            if (pre[k]) add(pre[k],a[k]);
            add(k,a[k]);
        }
        ans[q[i].id]=xo[q[i].r]^xo[q[i].l-1]^get(q[i].r)^get(q[i].l-1);
    }
    for (i=1;i<=m;i++)
        printf("%d
",ans[i]);
    return 0;
}
View Code

   E:在这里

原文地址:https://www.cnblogs.com/dramstadt/p/5742028.html