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 /**************************************************/
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 /**************************************************/
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 /**************************************************/