T1 中位数:二分答案
分析:
二分一个mid值,check中位数是否可以>=mid。
如何check?令小于mid的为-1,大于等于的为1,维护前缀最小值即可。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
inline LL read(){
LL 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<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MAXN=100005;
int n,len,a[MAXN],b[MAXN],c[MAXN],sum[MAXN],minsum[MAXN];
inline bool check(int mid){
minsum[0]=sum[0]=0;
for(int i=1;i<=n;i++){
if(a[i]<b[mid]) c[i]=-1;
else c[i]=1;
sum[i]=sum[i-1]+c[i];
minsum[i]=min(minsum[i-1],sum[i]);
if(i>=len&&sum[i]-minsum[i-len]>0) return 1;
}
return 0;
}
int main(){
n=read(),len=read();
for(int i=1;i<=n;i++) b[i]=a[i]=read();
sort(b+1,b+n+1);
int siz=unique(b+1,b+n+1)-b-1;
int l=1,r=siz,ans;
while(l<=r){
int mid=((l+r)>>1);
if(check(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",b[ans]);
return 0;
}
T2 数数字:数位DP
分析:
没什么好说的。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
typedef long long LL;
typedef pair<pair<int,LL>,pair<bool,bool> > Quadra;
#define Mp make_pair
LL l,r,L,R;
int dig[30],cnt;
map<Quadra,LL> f;
inline Quadra Mq(int x,LL y,bool z,bool zz){
return Mp(Mp(x,y),Mp(z,zz));
}
LL Dfs(int now,LL mul,bool free,bool pre0){
// cout<<now<<" "<<mul<<" "<<free<<" "<<pre0<<endl;
if(mul==0&&L>0) return 0;
if(mul>R&&L>0) return 0;
if(now==0) return L<=mul&&mul<=R;
Quadra sta=Mq(now,mul,free,pre0);
if(f.count(sta)) return f[sta];
LL ret=0;
for(int i=0;i<=9;i++){
if(!free&&i>dig[now]) break;
if(i==0){
if(pre0) ret+=Dfs(now-1,1,1,1);
else{
if(dig[now]==0) ret+=Dfs(now-1,0,free,0);
else ret+=Dfs(now-1,0,1,0);
}
}
else if(i==dig[now]){
ret+=Dfs(now-1,mul*i,free,0);
}
else{
ret+=Dfs(now-1,mul*i,1,0);
}
}
return f[sta]=ret;
}
inline LL Solve(LL x){
if(x<0) return 0;
f.clear();
cnt=0;
while(x){
dig[++cnt]=x%10;
x/=10;
}
return Dfs(cnt,1,0,1);
}
int main(){
scanf("%lld%lld%lld%lld",&l,&r,&L,&R);
if(l==r&&l==0){
if(L<=0&&r<=0) printf("1\n");
else printf("0\n");
return 0;
}
printf("%lld\n",Solve(r)-Solve(l-1));
return 0;
}
T3 保护:LCA+主席树
分析:
在每个守卫守卫的路径的u和v打上lca(u,v)的标记。
然后就变成询问子树第k小了。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <vector>
#define lowbit(x) ((x)&(-(x))
using namespace std;
typedef long long LL;
inline LL read(){
LL 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<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MAXN=400005;
int n,m,ecnt,head[MAXN];
int fa[MAXN],dep[MAXN],siz[MAXN],pc[MAXN],top[MAXN],id[MAXN],num[MAXN],tot;
int root[MAXN],lc[MAXN*24],rc[MAXN*24],sum[MAXN*24],loc,k;
vector<int> v1[MAXN];
struct Edge{
int to,nxt;
}e[MAXN<<1];
inline void add_edge(int bg,int ed){
ecnt++;
e[ecnt].to=ed;
e[ecnt].nxt=head[bg];
head[bg]=ecnt;
}
void dfs1(int x,int pre,int depth){
fa[x]=pre;
dep[x]=depth;
siz[x]=1;
int maxsiz=-1;
for(int i=head[x];i;i=e[i].nxt){
int ver=e[i].to;
if(ver==pre) continue;
dfs1(ver,x,depth+1);
siz[x]+=siz[ver];
if(siz[ver]>maxsiz){
maxsiz=siz[ver];
pc[x]=ver;
}
}
}
void dfs2(int x,int topf){
top[x]=topf;
id[x]=++tot;
num[tot]=x;
if(!pc[x]) return;
dfs2(pc[x],topf);
for(int i=head[x];i;i=e[i].nxt){
int ver=e[i].to;
if(ver==fa[x]||ver==pc[x]) continue;
dfs2(ver,ver);
}
}
inline int lca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
#define mid ((l+r)>>1)
int upd(int pre,int l,int r){
int o=++tot;
sum[o]=sum[pre];
lc[o]=lc[pre];
rc[o]=rc[pre];
if(l==r&&l==loc){
sum[o]++;
return o;
}
if(loc<=mid) lc[o]=upd(lc[pre],l,mid);
else rc[o]=upd(rc[pre],mid+1,r);
sum[o]=sum[lc[o]]+sum[rc[o]];
return o;
}
int query(int u,int v,int l,int r){
if(sum[v]-sum[u]<k) return -1;
if(l==r) return l;
if(sum[lc[v]]-sum[lc[u]]>=k) return query(lc[u],lc[v],l,mid);
else{
k-=sum[lc[v]]-sum[lc[u]];
return query(rc[u],rc[v],mid+1,r);
}
}
#undef mid
int main(){
n=read(),m=read();
for(int i=1;i<n;i++){
int u=read(),v=read();
add_edge(u,v);
add_edge(v,u);
}
dfs1(1,0,1);
dfs2(1,1);
for(int i=1;i<=m;i++){
int u=read(),v=read();
int _lca=lca(u,v);
v1[id[u]].push_back(id[_lca]);
v1[id[v]].push_back(id[_lca]);
}
tot=0;
for(int i=1;i<=n;i++){
root[i]=root[i-1];
for(int j=0;j<v1[i].size();j++){
loc=v1[i][j];
root[i]=upd(root[i],1,n);
}
}
int q=read();
while(q--){
int x=read();k=read();
int ret=query(root[id[x]-1],root[id[x]+siz[x]-1],1,n);
if(ret==-1) printf("0\n");
else printf("%d\n",dep[x]-dep[num[ret]]<0?0:dep[x]-dep[num[ret]]);
}
return 0;
}