zoukankan      html  css  js  c++  java
  • 分治分块与计算几何练习 [Cloned]

     https://cn.vjudge.net/contest/148706

    A

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int N=2e5+7;
    struct node{
        int l,r,t,pos;
        bool operator < (const node &a)const{
            return pos==a.pos?r<a.r:pos<a.pos;
        }
    }b[N];
    int n,m,l,r,a[N],f[N];
    ll res,ans1[N],ans2[N];
    ll gcd(ll a,ll b){
        if(!b) return a;
        return gcd(b,a%b);
    }
    int main(){
        n=read();m=read();
        for(int i=1;i<=n;i++) a[i]=read();
        int k=sqrt(n*1.0)+0.5;
        for(int i=1;i<=m;i++){
            b[i].l=read();b[i].r=read();
            b[i].t=i;b[i].pos=b[i].l/k;
        }
        sort(b+1,b+m+1);
        memset(f,0,sizeof f);
        l=1;r=0;res=0;
        for(int i=1;i<=m;i++){
            while(r>b[i].r){
                res-=(ll)f[a[r]]-1;
                f[a[r]]--;
                r--;
            }
            while(r<b[i].r){
                r++;
                f[a[r]]++;
                res+=(ll)f[a[r]]-1;
            }
            while(l>b[i].l){
                l--;
                f[a[l]]++;
                res+=(ll)f[a[l]]-1;
            }
            while(l<b[i].l){
                res-=(ll)f[a[l]]-1;
                f[a[l]]--;
                l++;
            }
            ans1[b[i].t]=res;
            ans2[b[i].t]=(ll)(r-l+1)*(r-l)/2;
        }
        for(int i=1;i<=m;i++){
            if(!ans1[i]){
                puts("0/1");
                continue;
            }
            ll gg=gcd(ans1[i],ans2[i]);
            printf("%lld/%lld
    ",ans1[i]/gg,ans2[i]/gg);
            //printf("%I64d/%I64d
    ",ans1[i]/gg,ans2[i]/gg);
        }
        return 0;
    }

    B

    //扫描线考精度,没什么技术含量 
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #define eps 1e-8
    using namespace std;
    int n,tot,cnt;
    double last,ans,pos[100005];
    struct P{double x,y;}p[105][3];
    struct L{P a,b;}l[105][3];
    struct seg{double l,r;}f[105];
    inline P operator -(P a,P b){return (P){a.x-b.x,a.y-b.y};}
    inline double operator *(P a,P b){return a.x*b.y-a.y*b.x;}//叉积 
    inline double operator /(P a,P b){return a.x*b.x+a.y*b.y;}//点积 
    inline P inter(L l1,L l2){
        double k1=(l2.b-l1.a)*(l1.b-l1.a),k2=(l1.b-l1.a)*(l2.a-l1.a),t=k1/(k1+k2);
        return (P){l2.b.x+(l2.a.x-l2.b.x)*t,l2.b.y+(l2.a.y-l2.b.y)*t};
    }
    inline bool judge(L l1,L l2){
        return fabs((l1.b.y-l1.a.y)*(l2.b.x-l2.a.x)-(l1.b.x-l1.a.x)*(l2.b.y-l2.a.y))>eps;
    }
    inline bool cmp(seg a,seg b){
        return fabs(a.l-b.l)<=eps?a.r<b.r:a.l<b.l;
    }
    inline double dcmp(double x){
        if(fabs(x)<=eps) return 0;
        else return x<0?-1:1;
    }
    inline bool cross(P a1,P a2,P b1,P b2){
        double c1=(a2-a1)*(b1-a1),c2=(a2-a1)*(b2-a1),c3=(b2-b1)*(a1-b1),c4=(b2-b1)*(a2-b1);
        return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
    }
    inline double calc(double x){
        L ln=(L){(P){x,0},(P){x,1}};
        int num;cnt=0;
        double y[4],h,ret=0;
        for(int i=1;i<=n;i++){
            double mn=min(p[i][0].x,min(p[i][1].x,p[i][2].x)),mx=max(p[i][0].x,max(p[i][1].x,p[i][2].x));
            if(x<mn+eps||x>mx-eps) continue;
            num=0;
            for(int j=0;j<=2;j++){
                if(judge(l[i][j],ln)){
                    P tmp=inter(l[i][j],ln);
                    if((l[i][j].a-tmp)/(l[i][j].b-tmp)>-eps) continue;
                    y[++num]=tmp.y;
                }
            }
            if(num>1) f[++cnt]=(seg){y[1],y[2]};
        }
        for(int i=1;i<=cnt;i++){
            if(f[i].l>f[i].r){
                swap(f[i].l,f[i].r);
            } 
        } 
        sort(f+1,f+cnt+1,cmp);
        for(int i=1;i<=cnt;i++){
            if(i==1||f[i].l>h+eps) ret+=f[i].r-f[i].l,h=f[i].r;
            else if(f[i].r>h+eps) ret+=f[i].r-h,h=f[i].r;
        }
        return ret;
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            for(int j=0;j<=2;j++){
                scanf("%lf%lf",&p[i][j].x,&p[i][j].y),pos[++tot]=p[i][j].x;
            }
        }
        for(int i=1;i<=n;i++){
            l[i][0]=(L){p[i][1],p[i][2]},
                l[i][1]=(L){p[i][0],p[i][2]},
                l[i][2]=(L){p[i][0],p[i][1]};
        }
        for(int i=1;i<n;i++){
            for(int j=i+1;j<=n;j++){
                for(int k1=0;k1<=2;k1++){
                    for(int k2=0;k2<=2;k2++){
                        if(cross(l[i][k1].a,l[i][k1].b,l[j][k2].a,l[j][k2].b)){
                            pos[++tot]=inter(l[i][k1],l[j][k2]).x;
                        } 
                    }
                }
            }
        }    
        sort(pos+1,pos+tot+1);
        last=pos[1];
        for(int i=2;i<=tot;i++){
            if(fabs(pos[i]-last)>eps){
                ans+=calc((pos[i]+last)/2)*(pos[i]-last);
                last=pos[i];
            }
        }
        ans-=eps;//eps!
        printf("%.2lf
    ",ans);
        return 0;
    }

    C

    //题意:n场考试中分别答对a_i题,总题数分别为b_i,允许去掉k场考试,求能达到的最高准确率。
    //二分比0/1分数规划慢,然而后者并不会 
    #include<cstdio>
    #include<algorithm>
    #define eps 1e-7
    using namespace std;
    const int N=1005;
    int n,k;
    double sum,a[N],b[N],t[N];
    int main(){
        while(scanf("%d%d",&n,&k)==2){
            if(!n) break;
            for(int i=0;i<n;i++) scanf("%lf",&a[i]);
            for(int i=0;i<n;i++) scanf("%lf",&b[i]);
            double l=0.0,r=1.0,mid;
            while(r-l>eps){
                mid=(l+r)/2.0;
                for(int i=0;i<n;i++) t[i]=a[i]-mid*b[i];
                sort(t,t+n);sum=0;
                for(int i=k;i<n;i++) sum+=t[i];
                if(sum>0) l=mid;
                else r=mid;
            }
            printf("%.0f
    ",mid*100);//g++,坑 
        }
        return 0;
    }

    D

    //simpson自适应公式
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    using namespace std;
    #define sqr(x) ((x)*(x))
    typedef double DB;
    const int maxn=510;const DB zero=1e-6;
    int n;DB alp,h,x[maxn],R[maxn],fx1[maxn],fx2[maxn],fy1[maxn],fy2[maxn];
    DB f(DB X){
        DB s=0;
        for(int i=1;i<=n;++i){
            if(fabs(x[i]-X)<R[i]) s=max(s,sqrt(sqr(R[i])-sqr(x[i]-X)));
            if(x[i+1]-x[i]>fabs(R[i+1]-R[i]) && fx1[i]<X && X<fx2[i])
                s=max(s,(fy2[i]-fy1[i])/(fx2[i]-fx1[i])*(X-fx1[i])+fy1[i]);
        }
        return s;
    }
    DB simpson(DB a,DB b,DB fa,DB fb,DB fm){return (b-a)/6*(fa+4*fm+fb);}//不知道怎么积出来的辛普森 
    DB area(DB l,DB fl,DB m,DB fm,DB r,DB fr,DB pre){
        DB ls=(l+m)/2,rs=(m+r)/2,fls=f(ls),frs=f(rs);
        DB la=simpson(l,m,fl,fm,fls),ra=simpson(m,r,fm,fr,frs);
        return fabs(la+ra-pre)<zero? pre:area(l,fl,ls,fls,m,fm,la)+area(m,fm,rs,frs,r,fr,ra);
    }
    int main(){
        scanf("%d%lf",&n,&alp);alp=1/tan(alp);
        for(int i=1;i<n+2;++i) scanf("%lf",&x[i]),h+=x[i],x[i]=h*alp;
        DB l=x[n+1],r=l;
        for(int i=1;i<n+1;++i)
            scanf("%lf",&R[i]),l=l<x[i]-R[i]? l:x[i]-R[i],r=r>x[i]+R[i]? r:x[i]+R[i];
        for(int i=1;i<n+1;++i)
            fx1[i]=x[i]+R[i]*(R[i]-R[i+1])/(x[i+1]-x[i]),fy1[i]=sqrt(sqr(R[i])-sqr(fx1[i]-x[i])),
            fx2[i]=x[i+1]+R[i+1]*(R[i]-R[i+1])/(x[i+1]-x[i]),fy2[i]=sqrt(sqr(R[i+1])-sqr(fx2[i]-x[i+1]));
        DB m=(l+r)/2,fm=f(m),fl=f(l),fr=f(r);
        printf("%.2lf",2*area(l,fl,m,fm,r,fr,simpson(l,r,fl,fr,fm)));
        return 0;
    }

    E

    //求图的绝对中心(这个点到所有点的最短距离的最大值最小)
    //reference:http://blog.csdn.net/crazy_ac/article/details/8816877 
    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int N=205;
    const int inf=0x3f3f3f3f;
    int n,m,d[N][N],di[N][N],rk[N][N];
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            d[i][i]=di[i][i]=0;
            for(int j=i+1;j<=n;j++){
                d[i][j]=d[j][i]=inf;
                di[i][j]=di[j][i]=inf;
            }
        } 
        for(int i=1,x,y,z;i<=m;i++){
            scanf("%d%d%d",&x,&y,&z);
            d[x][y]=d[y][x]=z;
            di[x][y]=di[y][x]=z;
        }
        for(int k=1;k<=n;k++){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
                }
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++) rk[i][j]=j;
            for(int j=1;j<=n;j++){
                for(int k=j+1;k<=n;k++){
                    if(d[i][rk[i][j]]>d[i][rk[i][k]]){
                        swap(rk[i][j],rk[i][k]);
                    }
                }
            }
        }
        int ans=inf;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(i==j) continue;
                ans=min(ans,d[i][rk[i][n]]<<1);
                ans=min(ans,d[j][rk[j][n]]<<1);
                for(int cmp=n,t=n-1;t>=1;t--){
                    if(d[j][rk[i][t]]>d[j][rk[i][cmp]]){
                        ans=min(ans,d[i][rk[i][t]]+d[j][rk[i][cmp]]+di[i][j]);
                        cmp=t;
                    }
                }
            }
        }
        printf("%.2lf
    ",(double)ans/2);
        return 0;
    }
  • 相关阅读:
    广度遍历有向图
    坚持的力量 第二十一篇
    坚持的力量 第二十二篇
    搜索引擎首页
    安装ubuntu
    最小生成树之Kruskal算法
    最小生成树之PRIM算法
    文件同步软件
    [恢]hdu 2151
    [恢]hdu 1396
  • 原文地址:https://www.cnblogs.com/shenben/p/6361373.html
Copyright © 2011-2022 走看看