zoukankan      html  css  js  c++  java
  • hdu5021 树状数组+二分

    这 题 说 的 是 给 了 一 个 K—NN    每次查询离loc 最近的k个数 然后将这k个数的权值加起来除以k 赋值给 loc 这个位置上的 权值

     我说说 我的做法 假如 查询的是loc 这个位置 k 个 ,然后 就让 L=1 R= loc 对于每个 二分 的 mid  假设mid 是这k个数最左的那个的下标 然后对于每个最左的下标 我们可以知道 这k 个数的最右点在哪里 然后就判断 这个区间是否要左移 或者右移 左移 R=mid 右移 L=mid+1 然后不断的去调整 找到最后的L和R后用树状数组去维护就好了
    #include <iostream>
    #include <cstdio>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    typedef int ll;
    const int max_n =100005;
    const int INF =(1e9)*2;
    struct point{
       ll loc,num;
       double val;
       bool operator <(const point A)const{
           return loc<A.loc;
       }
    }P[max_n];
    int n,m;
    double C[max_n];
    int lowbit(int x){
      return x&(-x);
    }
    void add(int x, double v){
         while(x<=n){
             C[x]+=v;
             x+=lowbit(x);
         }
    }
    double sum(int x){
        double ans=0;
        while(x>0){
             ans+=C[x];
             x-=lowbit(x);
        }
        return ans;
    }
    int id[max_n];
    ll dist[max_n];
    void binser(int &L, int &R,int loc, int num){
         L=max(1,loc-num);
         R= loc;
         ll S1,nu,S2;
         while(L<R){
             int mid =(R+L)/2;
             S1=dist[loc]-dist[mid];
             nu = num-(loc-mid)+loc;
             if(nu<loc){
                L=mid+1; continue;
             }
             if(nu>n){
                R=mid;continue;
             }
             S2=dist[nu]-dist[loc];
             if(S1>S2){
                L=mid+1;
             }else {
                R=mid;
             }
         }
         L = min(L,loc);
         R = num - ( loc - L ) + loc ;
         L = min( L + 1 , loc );
         R = max( loc , R - 1 );
         int ge = R-loc + loc - L;
         while(ge!=num){
           if(R>=n||(L>1&&dist[loc]-dist[L-1]<dist[R+1]-dist[loc])
           ||(L>1&&dist[loc]-dist[L-1]==dist[R+1]-dist[loc]&&P[L-1].num<P[R+1].num))
               L--;
            else R++;
            ge++;
         }
    }
    int main()
    {
        int cas;
        scanf("%d",&cas);
        while(cas--){
                for(int i=0; i<=n; i++)
                  C[i]=0.0;
            scanf("%d%d",&n,&m);
            for(int i =1; i<=n; i++){
                ll loc;
                double val;
                scanf("%d%lf",&loc,&val);
                P[i].loc=loc;
                P[i].num=i;
                P[i].val=val;
            }
            sort( P + 1 , P + n + 1 );
            for(int i=1; i <= n ;++i){
                    id[ P[i].num ] = i;
                    dist[ i ] = P[ i ].loc;
                    add( i , P[i].val );
             }
             dist[n+1]=INF;
             double ans=0;
             double S;
           while(m--){
                int loc, k;
                scanf("%d%d",&loc,&k);
                if(loc<1||k<1||k>=n)while(true);
                loc=id[loc];
                int L,R;
                binser(L,R,loc,k);
                add(loc,-P[loc].val);
                S =sum(R)-sum(L-1);
                S=S/k;
                ans=ans+S;
                add(loc,S);
                P[loc].val=S;
            }
            printf("%.3f
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    python 数据类型 变量 注释
    tornado 模版
    tornado 响应头 中断 状态码 工作流程
    tornado write render redirect IP
    tornado样板
    Celery实现异步任务
    Python pika简单实现RabbitMQ通信
    进程、线程与协程的比较
    使用 flask 实现 RESTful API
    阿里云服务器部署Tornado应用
  • 原文地址:https://www.cnblogs.com/Opaser/p/3986518.html
Copyright © 2011-2022 走看看