Today's test questions adapted from closing the roll to write ...... so aged problem solution.
A. ***** ***** greed
RT, the topic and people tell us that this question be greedy.
The optimal strategy must be dragged off again when disconnected (though do not know why).
If a sequence to meet the nature of the subject, then there must be $ gcd (a_i-a_ {i-1}, a_ {i + 1} -a_i, ...) $ 1 and not $ a_i, a_ {i + 1 }, ... $ vary. So the difference between two adjacent maintenance of each segment of gcd, encounters an element it does not meet or repeated ans ++. set to write more convenient.
#include<cstdio> #include<iostream> #include<cstring> #include<set> #include<cmath> using namespace std; const int N=100005; int n,a[N],ans=1; set<int> b; int gcd(int x,int y) { if(!y)return x; return gcd(y,x%y); } int now; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); b.insert(a[1]); for(int i=2;i<=n;i++) { now=gcd(now,abs(a[i]-a[i-1])); if(now==1||b.count(a[i])) { ans++; now=0; b.clear();b.insert(a[i]); } else b.insert(a[i]); } cout<<ans<<endl; return 0; }
B. ** witness *******
RT, the topic and people we witnessed over $ n ^ 2 $ 500,000.
Did not play offline dfs sequence std solution in direct relationship to the side with have included representatives of every answer to violence dfs statistical inquiry. Note that K = 1 special sentenced to build two-way side.
#include<cstdio> #include<iostream> #include<cstring> #include<vector> using namespace std; int n,m,cnt; const int N=500005;//change it! int head[N],nxt[N],to[N],tot,vis[N]; void add(int x,int y) { to[++tot]=y; nxt[tot]=head[x]; head[x]=tot; } int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } bool dfs(int x,int f,int aim) { if(x==aim)return 1; for(int i=head[x];i;i=nxt[i]) { if(to[i]!=f) if(dfs(to[i],x,aim))return 1; } return 0; } int main() { n=read();m=read();cnt=n; while(m--) { int opt=read(); if(!opt) { int op=read(),K=read(),now=++cnt; if(K==1) { int tmp=read(); add(now,tmp);add(tmp,now); } else if(op==0) { for(int i=1;i<=K;i++) add(now,read()); } else if(op==1) { for(int i=1;i<=K;i++) add(read(),now); } } else if(opt==1) { int x=read(),y=read(); printf("%d\n",dfs(x,0,y)); } } return 0; }
C. ** ****** accumulation
RT, the topic and told us to use the heap.
The equation can be a violent dp cut: $ dp [i] = \ min \ limits _ {j = max (0, iK)} ^ {i-1} dp [j] + max (sum [i] -sum [ j], b [j]) $
For all j, $ dp [j] + b [j] $ and $ dp [j] -sum [j] $ is a predetermined value
So with two stacks, respectively, to maintain both. Required $ dp [i] = min (heap1.top, heap2.top + sum [i]) $
First, check the first stack, if j is smaller than the withdrawn iK, pop continue to take off. If withdrawn than $ dp [j] -sum [j] + sum [i] $ small, add it to the second pile, pop off.
So take up to legal, the second stack is the same.
Time complexity $ O (nlogn) $
#include<cstdio> #include<iostream> #include<cstring> #include<queue> using namespace std; typedef long long ll; #define pa pair<ll,int> int n,K; const int N=500005; int a[N],b[N]; ll sum[N],dp[N]; priority_queue<pa,vector<pa>,greater<pa> >q1,q2; int main() { scanf("%d%d",&n,&K); for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum[i]=sum[i-1]+1LL*a[i]; for(int i=0;i<n;i++) scanf("%d",&b[i]); memset(dp,0x3f,sizeof(dp)); dp[0]=0; q1.push(make_pair(dp[0]+1LL*b[0],0)); for(int i=1;i<=n;i++) { ll val1=0x7ffffffffff,val2=0x7ffffffffff; while(!q1.empty()) { ll val=q1.top().first;int id=q1.top().second; if(id<i-K) { q1.pop();continue; } if(val<dp[id]-sum[id]+sum[i]) { q2.push(make_pair(dp[id]-sum[id],id));q1.pop(); continue; } val1=min(val1,val); break; } while(!q2.empty()) { ll val=q2.top().first; int id=q2.top().second; if(id<i-K) { q2.pop();continue; } val2=min(val2,val); break; } dp[i]=min(val1,val2+sum[i]); //cout<<i<<' '<<dp[i]<<endl; q1.push(make_pair(dp[i]+b[i],i)); } cout<<dp[n]<<endl; return 0; }