zoukankan      html  css  js  c++  java
  • 2016.7.22.noip2012D2

    mod:

    扩展欧几里德算法,而我没有复习,暴力的60

    事后后悔死

    classroom:

    线段树得90,T两个点。代码与问题如下:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 using namespace std;
     5 int n,m,s,t;
     6 long long r[1000005],d;
     7 struct stu
     8 {
     9     int l,r;
    10     long long mi,val;
    11 }tree[4000005];
    12 int minn(int q1,int q2)
    13 {
    14     if(q1>q2) return q2;
    15     return q1;
    16 }
    17 void pushdown(int v)
    18 {
    19     if(tree[v].l==tree[v].r) return ;
    20     tree[v<<1].val+=tree[v].val;
    21     tree[(v<<1)+1].val+=tree[v].val;
    22     tree[v<<1].mi-=tree[v].val;//-=忘了,-的只有本次的值也忘了 
    23     tree[(v<<1)+1].mi-=tree[v].val;
    24     tree[v].val=0;
    25 }
    26 void build(int left,int right,int u)
    27 {
    28     tree[u].l=left;
    29     tree[u].r=right;
    30     if(left==right)
    31     {
    32         tree[u].mi=r[left];
    33         return ;
    34     }
    35     int mid=(left+right)>>1;
    36     build(left,mid,u<<1);
    37     build(mid+1,right,(u<<1)+1);
    38     tree[u].mi=minn(tree[u<<1].mi,tree[(u<<1)+1].mi);
    39 }
    40 bool query(int u,int left,int right,long long dd)
    41 {
    42     bool flag;
    43     if(tree[u].l==left&&tree[u].r==right)
    44     {
    45         
    46         if(tree[u].mi>=dd) 
    47         {
    48             tree[u].mi-=dd;
    49             tree[u].val+=dd;
    50             return true;
    51         }
    52         return false;
    53     }
    54     if(tree[u].val) pushdown(u);
    55     int mid=(tree[u].l+tree[u].r)>>1;
    56     if(right<=mid) flag=query(u<<1,left,right,dd);
    57     else if(left>mid) flag=query((u<<1)+1,left,right,dd);
    58     else if(query(u<<1,left,mid,dd)&&query((u<<1)+1,mid+1,right,dd)) flag=true;
    59     else flag=false;
    60     tree[u].mi=minn(tree[u<<1].mi,tree[(u<<1)+1].mi);//向上更新,在合并的时候忘了 
    61     return flag;
    62 }
    63 int main()
    64 {
    65     freopen("classroom.in","r",stdin);
    66     freopen("classroom.out","w",stdout);
    67     scanf("%d %d",&n,&m);
    68     for(int i=1;i<=n;i++)
    69         scanf("%lld",&r[i]);
    70     build(1,n,1);
    71     for(int j=1;j<=m;j++)
    72     {
    73         scanf("%lld %d %d",&d,&s,&t);
    74         if(query(1,s,t,d)==false)
    75         {
    76            printf("-1
    ");
    77            printf("%d
    ",j);
    78            return 0;    
    79         }
    80     }
    81     printf("0
    ");
    82     return 0;
    83 }

    另,正解是二分订单,如下:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    using namespace std;
    int n,m,s[1000005],t[1000005],ans;
    int r[1000005],d[1000005],a[1000005];
    void depart(int l,int ri)
    {
        memset(a,0,sizeof(a));
        bool flag=false;
        if(l==ri)
        {
            return ;
        }
        int midd=(l+ri)>>1;
        int sum=0;
        for(int i=1;i<=midd;i++)
        {
            a[s[i]]+=d[i];
            a[t[i]+1]-=d[i];
        }
        for(int i=1;i<=n;i++)
            {
                sum+=a[i];
                if(sum>r[i])
                {
                   flag=true;    
                   break;
                }    
            }
        
        if(flag){
            ans = midd;
         depart(l,midd);
        }else depart(midd+1,ri);
    }
    int main()
    {
        freopen("classroom.in","r",stdin);
        freopen("classroom.out","w",stdout);
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&r[i]);
        for(int j=1;j<=m;j++)
            scanf("%d %d %d",&d[j],&s[j],&t[j]);
        depart(1,m);
        if(ans)
            {
               printf("-1
    ");
               printf("%d
    ",ans);
               return 0;    
            }
        printf("0
    ");
        return 0;
    }

    blockade:

    惊呆,看标答都看了1小时...借大神的程序配大神的注释与自己的理解。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #define INF 999999999999
    #define LL long long
    #define Max(x,y) if(x<y) x=y;
    #define N 100003
    using namespace std ;
    struct P{
        LL p,t;
        P():p(),t(){}
        P(const LL x,const LL y) : p(x),t(y){}   
    }army[N],edge[N];
    bool cmp(const P &x,const P &y){
        return x.t>y.t; 
    } 
    LL n,m,T;
    LL next[N*2],last[N*2],to[N*2];
    LL w[N*2];
    LL p[N],from[N],root[N];
    LL dis[N],left[N]; 
    bool use[N]; 
    queue<LL> q;
    inline void addedge(LL a,LL b,LL c){//存边的关系 
        next[++T]=last[a]; last[a]=T; to[T]=b ; w[T]=c;
        next[++T]=last[b]; last[b]=T; to[T]=a ; w[T]=c;
    }
    void fail(){//比较军队数和根节点连接的路径数,说白了特判 
        LL Tot=0;
        for(LL i=last[1];i;i=next[i]) ++Tot;
        if(Tot>m) {
            printf("-1");
            exit(0);
        }
    }
    LL pushup(LL now,LL f){//军队移到节点now(now父点是f)剩余的时间。 
         if(!next[last[now]]) {//叶子结点
           if(left[now]>=0ll) use[now]=1 ;//守住now结点 
            return left[now]   ;
         } 
         use[now]=1;//不赋值,有1组数据错;假设可以守住now结点 
         for(LL i=last[now];i;i=next[i]) 
          if(to[i]!=f){//不是父亲节点 
            Max(left[now],pushup(to[i],now)-w[i]);//now的时间选left[now]与下面结点剩的时间中的最大值 
            if(!use[to[i]]) use[now]=0;//now的子结点没守住,则now也可能没守住 
          }
         if(left[now]>=0) use[now]=1;//军队到now结点所剩时间>=0,能管住节点now 
         return left[now];
    }
    bool check(LL lim){
        LL numa=0,numb=0;
        memset(left,-1,sizeof left);//剩余时间 
        memset(use,0,sizeof use);//是否经过 
        memset(from,0,sizeof from);//从哪里来 
        for(LL i=1;i<=m;i++) 
          if(dis[p[i]]>=lim) 
            left[p[i]]=lim;//走不到根1结点,该军队的时限 
          else 
            army[++numa]=P(root[p[i]],lim-dis[p[i]]);//从根1下的root[p[i]]来,生活剩lim-dis[p[i]]时间 
        pushup(1,0);    
        for(LL i=last[1];i;i=next[i]) 
          if(!use[to[i]])
            edge[++numb]=P(to[i],w[i]);
        if(numb>numa) return false; // 军队不够 
        sort(army+1,army+numa+1,cmp);
        sort(edge+1,edge+numb+1,cmp);
        //----来自该节点的所剩时间最少的军队----  
        for(LL i=numa;i;i--)
           if(!from[army[i].p]) 
             from[army[i].p]=i;
        //-------------------------------------- 
        LL la=1,lb=1;
        memset(use,0,sizeof use); //归并,从大到小,有一个不满足就全不满足 
        use[0]=1;
        while(lb<=numb&&la<=numa){
           if(use[la]){
              ++la;
              continue ;    
           }
           if(!use[from[edge[lb].p]]){
              use[from[edge[lb].p]]=1;
              ++lb;
              continue ;
           }
           if(army[la].t<edge[lb].t) return false ;
           use[la]=1;
           ++la ;
           ++lb ; 
        }
        return true ; 
    }
    void prework(){
       q.push(1);//队列 
       use[1]=1;
       for(LL i=last[1];i;i=next[i]) root[to[i]]=to[i];//与1相连的所有点 ,父亲为自己 
       while(!q.empty()){//队列非空 
            LL now=q.front();
            q.pop();
            for(LL i=last[now];i;i=next[i]) 
            if(!use[to[i]]){
                if(now!=1) root[to[i]]=root[now];//记爸爸 
                dis[to[i]]=dis[now]+w[i];//深度 
                use[to[i]]=1;//走没走 
                q.push(to[i]);
            }
       }
    }
    int main(){
        freopen("blockade.in","r",stdin);
        freopen("blockade.out","w",stdout);
        scanf("%I64d",&n);
        LL a,b,c;
        for(LL i=1;i<n;i++){
            scanf("%I64d%I64d%I64d",&a,&b,&c);
            addedge(a,b,c);
        }
        scanf("%I64d",&m);
        fail();
        for(LL i=1;i<=m;i++) scanf("%I64d",&p[i]);
        LL ans,l=0,r=100000000000000LL;//时间范围,尽量取大 
        prework();//广搜预处理 
        while(l<=r){//二分时间 
            LL mid=(l+r)>>1;
            if(check(mid)){
                ans=mid;
                r=mid-1;
            } else l=mid+1;
        }
        printf("%I64d",ans); 
        return 0;   
    }
  • 相关阅读:
    百度“搜索设置”之等待页面加载完成的3中等待方式
    百度“搜索设置”之基于定位下拉框或者需要点击link才显示的下拉框,二次定位与多次定位实现的实际效果区别
    百度“搜索设置”之关于在页面定位某元素,而其中又参杂动态页面存在的问题解决方法
    兔展首页登录练习
    百度贴吧爬虫练习
    简述Session 、Cookie、cache 区别
    运行Shell脚本的几种方式解析
    (一)PHP简介
    road习题(二)
    road习题(一)
  • 原文地址:https://www.cnblogs.com/fisch/p/5697241.html
Copyright © 2011-2022 走看看