#include<bits/stdc++.h> #define next nxt usingnamespace std; intread(){ int c=0,nx,sign=1; while(!isdigit(nx = getchar())) if(nx=='-') sign=-1; while(isdigit(nx)) c=c*10+nx-'0',nx=getchar(); return sign*c; } constint N=2e6 + 20,M=N*2; int head[N],next[M],ver[M]; inlinevoidaddEdge(int u,int v){ staticint now = 0; next[++now]=head[u],head[u]=now,ver[now]=v; next[++now]=head[v],head[v]=now,ver[now]=u; } constint K = N * 2; double alpha = 0.7; int n, m, root; int sum[K], dat[K]; int ls[K], rs[K], sz[K]; double val[K]; int k;
classcmp { public: booloperator()(constint& lc, constint& rc)const{ return val[lc] < val[rc]; } }; set<int, cmp> col[N]; int *to_build; double tol, tor; inlineintNew(int x){ staticint now = 0; dat[++now] = x; return now; } inlinevoidpushup(int s){ sz[s] = sz[ls[s]] + sz[rs[s]] + 1; sum[s] = sum[ls[s]] + sum[rs[s]] + dat[s]; } inlineboolis(int s){ return sz[s] * alpha < max(sz[ls[s]], sz[rs[s]]); } voidadd(double p, int u, int x, int &s = root, double l=0, double r=1){ if(!s){ s = u; val[s] = (l + r) / 2; dat[s] = x; sz[s] = 1; return ; } if(p < val[s]) add(p, u, x, ls[s], l, val[s]); else add(p, u, x, rs[s], val[s], r); pushup(s); if(is(s)) to_build = &s, tol = l, tor = r; } voidmodify(double p, int x, int s = root){ if(p < val[s]) modify(p, x, ls[s]); elseif(p > val[s]) modify(p, x, rs[s]); else dat[s] += x; pushup(s); } intquery(double ql, double qr, int s = root, double l=0, double r=1){ if(!s) return0; if(ql <= l and r <= qr){ return sum[s]; } int ans = 0; if(ql < val[s]) ans = query(ql, qr, ls[s], l, val[s]); if(qr > val[s]) ans += query(ql, qr, rs[s], val[s], r); if(ql <= val[s] and qr >= val[s]) ans += dat[s]; return ans; } int stk[K], top; voiddfs(int s){ if(!s) return ; dfs(ls[s]); stk[++top] = s; dfs(rs[s]); } voidbuild(int &s, int l=1, int r=top, double vl=tol, double vr=tor){ if(l > r){ s = 0; return ; } int mid = (l + r) >> 1; s = stk[mid]; val[s] = (vl + vr) / 2; build(ls[s], l, mid - 1, vl, val[s]); build(rs[s], mid + 1, r, val[s], vr); pushup(s); } inlinevoidinsert(double p, int u, int x){ add(p, u, x); if(to_build){ top = 0; dfs(*to_build); build(*to_build); to_build = 0; } } namespace lca_bz{ int lg[N]; int fa[21][N],d[N]; intlca(int u,int v){ if(d[u] < d[v]) swap(u,v); while(d[u] > d[v]) u = fa[lg[d[u] - d[v]]][u]; if(u==v) return u; for(int i=lg[d[u]];i>=0;i--) if(fa[i][u] != fa[i][v]) u = fa[i][u], v = fa[i][v]; return fa[0][u]; } } usingnamespace lca_bz; intmain(){ // 强制在线版标程 // fclose(stderr); n = read(), m = read(); d[0] = -1; int cntt = 0; for(int i=1;i<=n;i++) lg[i] = lg[i - 1] + (1 << lg[i - 1] == i); for(int i=0;i<=n;i++) --lg[i]; int pre = 0; while(m--){ int op = read(), u = read() ^ pre, f, c; if(op == 0){ cntt++; f = read() ^ pre, c = read() ^ pre; d[u] = d[f] + 1; fa[0][u] = f; for(int i=1, tt = lg[d[u]];i<=tt;i++) fa[i][u] = fa[i - 1][fa[i - 1][u]]; insert(val[f], u, 1); insert(val[u], u + n, 0); auto &cc = col[c]; auto lp = cc.lower_bound(u), rp = cc.upper_bound(u); auto lt = lp != cc.begin(), rt = rp != cc.end(); if(lt){ lp--; f = lca(u, *lp); modify(val[f], -1); } if(rt){ f = lca(u, *rp); modify(val[f], -1); } if(lt and rt){ f = lca(*lp, *rp); modify(val[f], 1); } cc.insert(u); }else{ printf("%d\n", pre = query(val[u], val[u + n])); pre = query(val[u], val[u + n]); } } }
int Max[MAXN][21]; intQuery(int l,int r) { int k=log2(r-l+1); return std::max(Max[l][k],Max[r-(1<<k)+1][k]); } inlineintread() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} return x*f; } voidJiuCherish(){ int N=read(); for(int i=0;i<N;i++) { Max[i][0]=read(); a[i] = Max[i][0]; } for(int j=1;j<=21;j++) for(int i=1;i+(1<<j)-1<=N;i++) Max[i][j]=std::max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]); int ans = 0; int now = 0; while(now < N - 1){ int m = Query(now + 1,N - 1); now += 1; // std::cout << m << endl; while(a[now] < m) now++; ans++; } ans -= 1; std::cout << ans << endl; }
现已知每天都会发出 m 辆公交车,在手机上它可以查出这 m 辆公交车的发车时刻第 t_i 分钟,并且他还知道所有的站点信息,总共有 n 个公交车站点,第 i 个站点距离发车点的距离为 d_i 米。已知公交车的速度为 1 米/分钟,发车点和所有的站点都在一条直线上, 每次公交车从发车点出发后,依次经过每个站点。他想知道能否设计一个程序,当每次一个乘客在某个时刻时到达某个站点时,可以直接告诉他需要等待的时间?
我们在距离为 d 的车站在 t 时刻开始等候,其实就相当于我们在距离为 0 的车站在 t~d 时刻开始等候。因为一辆车在某个时间到距离为 d 的车站,那么在 d 分钟前一定到距离为 0 的车站,所以两者的到站顺序是完全一致的。这样就不需要给每个公交车的发车时刻都加上一个 d,而只需要在二分查找的时候找 t~d 的时刻后第一辆发的车就可以了。
i: 1 D 1 i: 2 L D 1 2 i: 3 D L D 1 2 3 i: 4 L D D L 1 2 4 3 i: 5 D L L D D 1 2 4 5 3 i: 6 L D D L D L 1 2 4 3 6 5 i: 7 D L L D D D L 1 2 4 3 5 7 6 i: 8 L D D L L D D L 1 2 4 3 7 6 8 5 i: 9 D L L D D L D D L 1 2 4 3 7 8 5 9 6 i: 10 L D D L L L L D D D 1 2 4 3 7 5 9 6 10 8 i: 11 D L L D D D L L L D D 1 2 4 3 7 5 6 10 8 11 9 i: 12 L D D L L L D D L L D D 1 2 4 3 7 5 10 8 11 9 12 6 i: 13 D L L D D D L D D L L D L 1 2 4 3 7 5 10 11 9 12 6 13 8 i: 14 L D D L L L D L D D L D D L 1 2 4 3 7 5 10 9 12 6 13 8 14 11 i: 15 D L L D D D L D L D L L D D L 1 2 4 3 7 5 10 9 6 13 8 14 11 15 12 i: 16 L D D L L L D L L D D L L D D D 1 2 4 3 7 5 10 9 13 8 14 11 15 12 16 6 i: 17 D L L D D D L D D L D D L L L D L 1 2 4 3 7 5 10 9 13 14 11 15 12 16 6 17 8 i: 18 L D D L L L D L L L L D D D L D D D 1 2 4 3 7 5 10 9 13 11 15 12 16 6 17 8 18 14 其中L 表示 LIVE, D表示DIE
通过表规律不难发现:
对于 m + 1,n 这个区间是没有操作的,因此 前 m 个数的前半部分是以 m 开头,2 为公差递减到 1 或者 2 的等差数列,后半部分以 1,2 中剩余的那个开头,以 2 为公差递增到 **m − 1 **
int bit[MAXN]; int n,k; intsum(int i){ int s=0; while (i>0){ s+=bit[i]; i-=(i&(-i)); } return s; } voidadd(int i,int x){ while (i<=n){ bit[i]+=x; i+=(i&(-i)); } } intbinary_search(int id){ int l=0,r=n+1; while (l<r){ int mid=(l+r)>>1; if (sum(mid)<id)l=mid+1; else r=mid; } return l; } voidJiuCherish(){ while (std::cin >> n >> k){ int id=1; memset(bit,0,sizeof(bit)); for (int i=1;i<=n;i++) add(i,1); for (int i=1;i<=n-1;i++){ id=(id+k-2)%(n-i+1)+1; int newid=binary_search(id); printf("%d ",newid); add(newid,-1); } } }