2016-浙江理工新生赛-部分题解

巴比伦花园

        link :http://oj.acm.zstu.edu.cn/JudgeOnline/problem.php?id=4239

       对于新生还是比较难;

我是用 RMQ + 二分 写的; 因为  fi[i]  数组代表从i开始最长到哪里,因为要求最长,所以第一个一定是1, i 是单调的,fi 数组也是单调的,所以可以二分;二分找刚刚在区间的,完全在区间用RMQ 离线查询;


 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cctype>
  4 #include <cmath>
  5 #include <set>
  6 #include <map>
  7 #include <list>
  8 #include <queue>
  9 #include <deque>
 10 #include <stack>
 11 #include <string>
 12 #include <vector>
 13 #include <iostream>
 14 #include <algorithm>
 15 #include <stdlib.h>
 16 #include <time.h>
 17  
 18 using namespace std;
 19 typedef long long LL;
 20 const int INF=2e9+1e8;
 21 const int MOD=1e9+7;
 22 const int MAXSIZE=1e6+5;
 23 const double eps=0.0000000001;
 24 void fre()
 25 {
 26     freopen("in.txt","r",stdin);
 27     freopen("out.txt","w",stdout);
 28 }
 29 #define memst(a,b) memset(a,b,sizeof(a))
 30 #define fr(i,a,n) for(int i=a;i<n;i++)
 31  
 32  
 33 const int MAXN=1e5+10;
 34 
 35 int n,k,q;
 36 LL input[MAXN];
 37 int fi[MAXN];
 38 
 39 struct RMQ
 40 {
 41     int dp[MAXN][20];
 42     void init()
 43     {
 44         for(int i=1;i<=n;i++) dp[i][0]=fi[i];
 45         for(int i=1;i<20;i++) 
 46             for(int j=1;j<=n;j++)    
 47                 if(j+(1<<i)-1<=n) dp[j][i]=max(dp[j][i-1],dp[j+(1<<(i-1))][i-1]);
 48     }
 49     int query(int l,int r)
 50     {
 51         if(l>r) return -1;
 52         if(l==r) return fi[l];
 53         int _k=(int)log2(r-l+1);
 54         return max(dp[l][_k],dp[r-(1<<_k)+1][_k]);
 55     }
 56 }rmq;
 57 
 58 int query(int l,int st)
 59 {
 60     for(int i=l;i<=n;i++)
 61         if(input[i]<1+k*((LL)i-st)) return i-st;
 62     return n-st+1;
 63 }
 64 int findR(int L,int R,int& b)
 65 {
 66     int l=1,r=n;
 67     while(1)
 68     {
 69         int mid=(l+r)>>1;
 70         if(fi[mid]+mid-1>=R&&fi[mid-1]+mid-2<R) 
 71         {
 72             b=mid-1;
 73             return R-max(L,mid)+1;
 74         }
 75         if(fi[mid]+mid-1>=R) r=mid;
 76         else l=mid+1;
 77     }
 78 }
 79 int findL(int L,int R,int& a)
 80 {
 81     int l=1,r=n;
 82     while(1)
 83     {
 84         int mid=(l+r)>>1;
 85         if(mid<=L&&mid+1>L) 
 86         {
 87             a=mid+1;
 88             return min(R,mid+fi[mid]-1)-L+1;
 89         }
 90         if(mid<=L) l=mid+1;
 91         else r=mid;
 92     }
 93 }
 94 int main()
 95 {
 96     int ncase;
 97     scanf("%d",&ncase);
 98     while(ncase--)
 99     {
100         scanf("%d%d%d",&n,&k,&q);
101         fi[0]=-INF;
102         for(int i=1;i<=n;i++)
103             scanf("%lld",&input[i]);
104         for(int i=1;i<=n;i++)
105             fi[i]=query(max(i-1+fi[i-1],i),i);
106         fi[n+1]=INF;
107         rmq.init();
108         while(q--)
109         {
110             int l,r,a,b;
111             scanf("%d%d",&l,&r);
112             int maxnum=max(findL(l,r,a),findR(l,r,b));
113             printf("%d\n",max(rmq.query(a,b),maxnum));
114         }
115     }
116     return 0;
117 }
118 
119 /**************************************************/
120 /**             Copyright Notice                 **/
121 /**  writer: wurong                              **/
122 /**  school: nyist                               **/
123 /**  blog  : http://blog.csdn.net/wr_technology  **/
124 /**************************************************/
View Code

 


 

D  题也是同一种套路; RMQ + 二分

 

4241: 圣杯战争

 

 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cctype>
  4 #include <cmath>
  5 #include <set>
  6 #include <map>
  7 #include <list>
  8 #include <queue>
  9 #include <deque>
 10 #include <stack>
 11 #include <string>
 12 #include <vector>
 13 #include <iostream>
 14 #include <algorithm>
 15 #include <stdlib.h>
 16 #include <time.h>
 17 
 18 using namespace std;
 19 typedef long long LL;
 20 const int INF=2e9+1e8;
 21 const int MOD=1e9+7;
 22 const int MAXSIZE=1e6+5;
 23 const double eps=0.0000000001;
 24 void fre()
 25 {
 26     freopen("in.txt","r",stdin);
 27     freopen("out.txt","w",stdout);
 28 }
 29 #define memst(a,b) memset(a,b,sizeof(a))
 30 #define fr(i,a,n) for(int i=a;i<n;i++)
 31 
 32 
 33 const int MAXN=2e5+10;
 34 
 35 int n,m,q,total,ans;
 36 LL atk[MAXN],presum[MAXN];
 37 int ap[MAXN],pos[MAXN];
 38 pair<int,int> seg[MAXN],Interval[MAXN];
 39 
 40 struct RMQ
 41 {
 42     int dp[MAXN][20];
 43     void init()
 44     {
 45         for(int i=1;i<total;i++) dp[i][0]=Interval[i].second-Interval[i].first+1;
 46         for(int i=1;i<20;i++)
 47             for(int j=1;j<total;j++)
 48                 if(j+(1<<i)-1<total) dp[j][i]=max(dp[j][i-1],dp[j+(1<<(i-1))][i-1]);
 49     }
 50     int query(int l,int r)
 51     {
 52         if(l>r) return 0;
 53         int _k=(int)log2(r-l+1);
 54         return max(dp[l][_k],dp[r-(1<<_k)+1][_k]);
 55     }
 56 }rmq;
 57 bool cmp(pair<int,int> a,pair<int,int> b)//按照 first 从小到大,first 一样的按照 second 的从大到小
 58 {
 59     if(a.first!=b.first) return a.first<b.first;
 60     else return a.second>b.second;
 61 }
 62 bool cmp1(pair<int,int> a,int val)
 63 {
 64     return a.first<val;
 65 }
 66 bool cmp2(pair<int,int> a,int val)
 67 {
 68     return a.second<val;
 69 }
 70 int query(int l,int r)
 71 {
 72     l=l^ans,r=r^ans;
 73     if(l>r) swap(l,r);
 74     l=max(1,l),r=min(n,r);
 75  //   printf("query %d %d\n",l,r);
 76     int fl,fr,maxnum;
 77     fl=lower_bound(Interval+1,Interval+total,l,cmp1)-Interval-1;
 78     fr=lower_bound(Interval+1,Interval+total,r,cmp2)-Interval;
 79   //
 80     int ans1=min(Interval[fl].second,r)-max(l,Interval[fl].first)+1;
 81     int ans2=min(r,Interval[fr].second)-max(l,Interval[fr].first)+1;
 82     if(fl>=total||fl<=0) ans1=-1;
 83     if(fr>=total||fr<=0) ans2=-1;
 84     maxnum=max(ans1,ans2);
 85    // printf("ans= %d %d %d\n",ans1,ans2,rmq.query(fl+1,fr-1));
 86     return max(rmq.query(fl+1,fr-1),maxnum);
 87 }
 88 void  debug(int k)
 89 {
 90 //    for(int i=0;i<k;i++)
 91 //        printf("seg[%d] : %d %d\n",i,seg[i].first,seg[i].second);
 92 //    printf("\n***********************************\n");
 93     printf("total=%d\n",total);
 94     for(int i=1;i<total;i++)
 95         printf("seg[%d] : %d %d\n",i,Interval[i].first,Interval[i].second);
 96     printf("\n***********************************\n");
 97 }
 98 LL getval(int l,int r)
 99 {
100     return presum[r]-presum[l-1];
101 }
102 int Lpos(int _pos,int _ap)
103 {
104     int l=1,r=_pos;
105     while(1)
106     {
107         int mid=(l+r)>>1;
108         if((mid==1&&getval(mid,_pos)<=_ap)||(getval(mid,_pos)<=_ap&&getval(mid-1,_pos)>_ap)) return mid;
109         if(getval(mid,_pos)<=_ap) r=mid;
110         else l=mid+1;
111     }
112 }
113 int Rpos(int _pos,int _ap)
114 {
115     int l=_pos,r=n;
116     while(1)
117     {
118         int mid=(l+r)>>1;
119         if((mid==n&&getval(_pos,mid)<=_ap)||(getval(_pos,mid)<=_ap&&getval(_pos,mid+1)>_ap)) return mid;
120         if(getval(_pos,mid)<=_ap) l=mid+1;
121         else r=mid;
122     }
123 }
124 int main()
125 {
126     int ncase;
127     scanf("%d",&ncase);
128     while(ncase--)
129     {
130         scanf("%d%d%d",&n,&m,&q);
131         presum[0]=0;
132         for(int i=1;i<=n;i++)
133         {
134             scanf("%lld",&atk[i]);
135             presum[i]=atk[i]+presum[i-1];
136         }
137         for(int i=0;i<m;i++)
138             scanf("%d",&pos[i]);
139         for(int i=0;i<m;i++)
140             scanf("%d",&ap[i]);
141         int k=0;
142         presum[n+1]=INF;
143         for(int i=0;i<m;i++)
144         {
145             if(ap[i]<atk[pos[i]]) continue;
146             seg[k].first=Lpos(pos[i],ap[i]),seg[k++].second=pos[i];
147             seg[k].first=pos[i],seg[k++].second=Rpos(pos[i],ap[i]);
148         }
149         // OK;
150         if(k==0)
151         {
152             int l,r;
153             while(q--) scanf("%d%d",&l,&r),printf("0\n");
154             continue;
155         }
156         sort(seg,seg+k,cmp);//OK;
157         total=2;
158         Interval[1]=seg[0];
159         for(int i=1;i<k;i++)
160             if(seg[i].second>Interval[total-1].second)
161                 Interval[total++]=seg[i];
162         rmq.init();
163         Interval[0].first=Interval[0].second=-1;
164         Interval[total].first=Interval[total].second=INF;
165         ans=0;
166       //  debug(k);
167         while(q--)
168         {
169             int l,r;
170             scanf("%d%d",&l,&r);
171             printf("%d\n",ans=query(l,r));
172         }
173     }
174     return 0;
175 }
176 
177 /**************************************************/
178 /**             Copyright Notice                 **/
179 /**  writer: wurong                              **/
180 /**  school: nyist                               **/
181 /**  blog  : http://blog.csdn.net/wr_technology  **/
182 /**************************************************/
View Code

 


 

4248: KI的目标

 

  1 /*
  2 如果 dis(a,b)>=val[a]-val[b] && dis[b,c]>=val[b]-val[c];
  3 那么 dis(a,c)>=val[a]-val[c];
  4 所以 只需要判断 val[现在的点]-val[下一个点]>边权值  如果真就不统计;
  5 */
  6 #include <cstdio>
  7 #include <cstring>
  8 #include <cctype>
  9 #include <cmath>
 10 #include <set>
 11 #include <map>
 12 #include <list>
 13 #include <queue>
 14 #include <deque>
 15 #include <stack>
 16 #include <string>
 17 #include <vector>
 18 #include <iostream>
 19 #include <algorithm>
 20 #include <stdlib.h>
 21 #include <time.h>
 22 
 23 using namespace std;
 24 typedef long long LL;
 25 const int INF=2e9+1e8;
 26 const int MOD=1e9+7;
 27 const int MAXSIZE=1e6+5;
 28 const double eps=0.0000000001;
 29 void fre()
 30 {
 31     freopen("in.txt","r",stdin);
 32     freopen("out.txt","w",stdout);
 33 }
 34 #define memst(a,b) memset(a,b,sizeof(a))
 35 #define fr(i,a,n) for(int i=a;i<n;i++)
 36 
 37 
 38 
 39 const int MAXN = 1000000+10;
 40 struct Node
 41 {
 42     int to,next,val;
 43 }edge[MAXN<<1];
 44 int first[MAXN],ntot;
 45 void init()
 46 {
 47     ntot=0;
 48     memset(first,-1,sizeof(first));
 49 }
 50 void addedge(int s,int t,int val)
 51 {
 52     edge[ntot].to=t,edge[ntot].val=val;
 53     edge[ntot].next=first[s];
 54     first[s]=ntot++;
 55 }
 56 int val[MAXN];
 57 int n;
 58 
 59 int dfs (int o,int now)
 60 {
 61     int res=1;
 62     for (int i=first[now],to,value; ~i; i=edge[i].next)
 63     {
 64         to=edge[i].to, value=edge[i].val;
 65         if (to==o) continue;
 66         if (val[now]-val[to]>value)  //val(v)<val(u)+path(u)-Path(v)  那么val(u)+path(u)取最大
 67         {
 68             continue;
 69         }
 70         res += dfs (now, to);
 71     }
 72     return res;
 73 }
 74 
 75 int main ()
 76 {
 77     int ncase;
 78     scanf ("%d", &ncase);
 79     while(ncase--)
 80     {
 81         scanf ("%d", &n);
 82         init();
 83         for (int i=1,u,v,w; i<n; i++)
 84         {
 85             scanf ("%d%d%d", &u, &v, &w);
 86             addedge(u,v,w);
 87             addedge(v,u,w);
 88         }
 89         for (int i=1; i<=n; i++) scanf ("%d", val+i);
 90         printf ("%d\n", dfs (1, 1));
 91     }
 92     return 0;
 93 }
 94 
 95 
 96 
 97 /**************************************************/
 98 /**             Copyright Notice                 **/
 99 /**  writer: wurong                              **/
100 /**  school: nyist                               **/
101 /**  blog  : http://blog.csdn.net/wr_technology  **/
102 /**************************************************/
View Code

 

posted @ 2016-11-22 23:30  Code-dream  阅读(248)  评论(0编辑  收藏  举报