学军NOIP2016模拟赛1
Posted ziliuziliu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学军NOIP2016模拟赛1相关的知识,希望对你有一定的参考价值。
GTMD这么水的一套题没有AK
T1:妥妥的二分答案,贪心check。
T2:问题可以转化为最长上升(还是下降我记不住了)子序列。
T3:发现点被覆盖上的顺序是一定的。求出这个顺序,第一个操作在线段树上二分,第二个操作是找到这个点最上面那个有人的点,把他的状态变为没人。
P.S.常数这么大也能过。。。
然而一开始260为什么呢。。
anc开的maxv*20还TMfor到了20。。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define maxn 100500 #define eps 1e-6 #define inf 0x7f7f7f7f7f7f7f7fLL using namespace std; long long n,h,x; double l=1,r=2000000000,ans; vector <long long> v[maxn]; bool check(double x) { double ret=0; for (long long i=1;i<=n;i++) { double mx=-inf; for (long long j=1;j<=h;j++) mx=max(mx,(double)v[i][j]-x*j); ret+=mx; } if (ret>=0) return true; return false; } int main() { scanf("%lld%lld",&n,&h); for (long long i=1;i<=n;i++) { v[i].push_back(0); for (long long j=1;j<=h;j++) { scanf("%lld",&x); v[i].push_back(v[i][j-1]+x); } } while (r-l>=eps) { double mid=(l+r)/2; if (check(mid)) {ans=l=mid;} else r=mid; } printf("%.4lf\n",ans); return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 100500 using namespace std; int n,a[maxn],b[maxn],x,t[maxn],ans=0,ret=0; int lowbit(int x) {return (x&(-x));} void modify(int x,int val) { for (int i=x;i<=n;i+=lowbit(i)) t[i]=max(t[i],val); } int ask(int x) { int ret=0; for (int i=x;i>=1;i-=lowbit(i)) ret=max(ret,t[i]); return ret; } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<=n;i++) { scanf("%d",&x); b[x]=i; } for (int i=1;i<=n;i++) { ret=ask(n-b[a[i]]+1); ans=max(ans,ret+1); modify(n-b[a[i]]+1,ret+1); } printf("%d\n",ans); return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define maxv 100500 using namespace std; int n,m,x,y,g[maxv],nume=1,op,dfn[maxv],fdfn[maxv],times=0,dis[maxv],anc[maxv][20]; int root,tot=0,ls[maxv<<2],rs[maxv<<2],sum[maxv<<2],lazy[maxv<<2]; vector <int> v[maxv]; void dfs(int x,int fath) { for (int i=0;i<v[x].size();i++) { int pos=v[x][i]; if (pos==fath) continue; anc[pos][0]=x;dis[pos]=dis[x]+1; dfs(pos,x); } dfn[x]=++times;fdfn[times]=x; } void get_table() { for (int i=1;i<=19;i++) for (int j=1;j<=n;j++) anc[j][i]=anc[anc[j][i-1]][i-1]; } void build(int &now,int left,int right) { now=++tot;sum[now]=right-left+1;lazy[now]=0; if (left==right) return; int mid=left+right>>1; build(ls[now],left,mid); build(rs[now],mid+1,right); } void pushdown(int now) { if (!lazy[now]) return; lazy[ls[now]]=lazy[rs[now]]=lazy[now]; sum[ls[now]]=sum[rs[now]]=0;lazy[now]=0; } void pushup(int now) { sum[now]=sum[ls[now]]+sum[rs[now]]; } int ask1(int now,int left,int right,int x) { pushdown(now); if (left==right) return left; int mid=left+right>>1,k=sum[ls[now]]; if (x<=k) return ask1(ls[now],left,mid,x); else return ask1(rs[now],mid+1,right,x-k); } void modify1(int now,int left,int right,int l,int r) { if ((left==l) && (right==r)) { lazy[now]=1;sum[now]=0; return; } int mid=left+right>>1; if (r<=mid) modify1(ls[now],left,mid,l,r); else if (l>=mid+1) modify1(rs[now],mid+1,right,l,r); else { modify1(ls[now],left,mid,l,mid); modify1(rs[now],mid+1,right,mid+1,r); } pushup(now); } int ask2(int now,int left,int right,int pos) { pushdown(now); if (left==right) return sum[now]; int mid=left+right>>1; if (pos<=mid) return ask2(ls[now],left,mid,pos); else return ask2(rs[now],mid+1,right,pos); } void modify2(int now,int left,int right,int pos) { pushdown(now); if (left==right) {sum[now]=1;return;} int mid=left+right>>1; if (pos<=mid) modify2(ls[now],left,mid,pos); else modify2(rs[now],mid+1,right,pos); pushup(now); } void work1() { int pos=ask1(root,1,n,x); printf("%d\n",fdfn[pos]); modify1(root,1,n,1,pos); } void work2() { int ret=x; for (int i=19;i>=0;i--) { if (!anc[ret][i]) continue; if (!ask2(root,1,n,dfn[anc[ret][i]])) ret=anc[ret][i]; } printf("%d\n",dis[x]-dis[ret]); modify2(root,1,n,dfn[ret]); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n-1;i++) { scanf("%d%d",&x,&y); v[x].push_back(y);v[y].push_back(x); } for (int i=1;i<=n;i++) sort(v[i].begin(),v[i].end()); dfs(1,0);get_table(); build(root,1,n); for (int i=1;i<=m;i++) { scanf("%d%d",&op,&x); if (op==1) work1(); else work2(); } return 0; }
以上是关于学军NOIP2016模拟赛1的主要内容,如果未能解决你的问题,请参考以下文章