78-76: 模拟赛
$sol$
暴力判断,枚举和的约数判断
注意 0 的特判
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; #define YES puts("YES") #define NO puts("NO") char s[N]; int Len; bool See(int x) { int tot = 0; for(int i = 1; i <= Len; i ++) { if(s[i] - '0' > x) return 0; tot += s[i] - '0'; if(tot % x == 0) tot = 0; if(tot > x) return 0; } return 1; } int main() { int t; cin >> t; while(t --) { scanf("%s", s + 1); Len = strlen(s + 1); int sum = 0; int Min = (1 << 30); for(int i = 1; i <= Len; i ++) sum += s[i] - '0', Min = min(Min, s[i] - '0'); if(sum == 0) { YES; continue; } bool flag = 1; for(int i = Min + 1; i < sum; i ++) { if(sum % i) continue; if(See(i)) { YES; flag = 0; break; } } if(flag) NO; } return 0; }
这这这,这什么破题
$sol$
$f_u$ 表示以 $u$ 为根的子树中被覆盖的点的点权和最大为多少
若点 $u$ 不被覆盖则 $f_u = \sum f_v$,v 是点 u 的儿子结点
若 u 被路径 $(x, y)$ 覆盖,且 $u$ 是 $x$ 和 $y$ 的最近公共祖先
$f_u = \sum a_v$, v 在路径(x, y) 上 + $\sum f_v$, v 不在路径(x,y)上,v的父亲在路径(x,y)上
用线段树维护每个点到根结点的信息,或者树链剖分维护路径上的信息
时间复杂 O(nlogn)
$code$
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> using namespace std; typedef long long ll; typedef long double ld; typedef pair<int,int> pr; #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define Rep(i,u) for(int i=head[u];i;i=Next[i]) ll read() { ll ans=0; char last=' ',ch=getchar(); while(ch<'0' || ch>'9')last=ch,ch=getchar(); while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); if(last=='-')ans=-ans; return ans; } //head #define N 210000 int head[N],v[N],Next[N],dep[N],fa[N][18],a[N],st[N],ed[N]; int n,num,m,num2,num3,nn,head2[N],v2[N],Next2[N]; int lson[N],rson[N],root=0; ll Sum,f[N],s[N][2],sa[N]; struct node { int x,y,z; } q[N]; void add(int x,int y) { v[++num]=y; Next[num]=head[x]; head[x]=num; } void add2(int x,int y) { v2[++num2]=y; Next2[num2]=head2[x]; head2[x]=num2; } int Q[N],siz[N]; void dfs(int u) { int t=0,w=1; Q[1]=u; while(t<w) { u=Q[++t]; sa[u]=sa[fa[u][0]]+a[u]; for(int i=1; (1<<i)<=dep[u]; i++) fa[u][i]=fa[fa[u][i-1]][i-1]; for(int i=head[u]; i; i=Next[i]) if(v[i]!=fa[u][0]) { fa[v[i]][0]=u; dep[v[i]]=dep[u]+1; Q[++w]=v[i]; } siz[u]=1; } per(i,w,2)siz[fa[Q[i]][0]]+=siz[Q[i]]; st[1]=1; rep(i,1,n) { u=Q[i]; int t=st[u]; ed[u]=st[u]+siz[u]-1; for(int i=head[u]; i; i=Next[i]) if(v[i]!=fa[u][0])st[v[i]]=t+1,t+=siz[v[i]]; } } int lca(int x,int y) { if(dep[x]<dep[y])swap(x,y); per(i,17,0) if(dep[x]-(1<<i)>=dep[y])x=fa[x][i]; if(x==y)return x; per(i,17,0) if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i]; return fa[x][0]; } int lca2(int x,int y) { per(i,17,0) if(dep[x]-(1<<i)>dep[y])x=fa[x][i]; return x; } void change(int &u,int l,int r,int x,int y,ll w,int k) { if(x>r || y<l)return ; if(!u)u=++num3; if(x<=l && y>=r) { s[u][k]+=w; return; } int mid=(l+r)>>1; change(lson[u],l,mid,x,y,w,k); change(rson[u],mid+1,r,x,y,w,k); } ll find(int u,int l,int r,int x,int k) { if(!x)return 0; if(!u)return 0; if(l==r)return s[u][k]; int mid=(l+r)>>1; if(x<=mid)return find(lson[u],l,mid,x,k)+s[u][k]; else return find(rson[u],mid+1,r,x,k)+s[u][k]; } ll work2(int x,int y) { return find(root,1,n,st[x],1)-find(root,1,n,st[fa[y][0]],1)-(find(root,1,n,st[x],0)-find(root,1,n,st[y],0)); } ll work(int x,int y,int z) { if(dep[x]<dep[y])swap(x,y); if(y==z)return work2(x,y)+sa[x]-sa[fa[y][0]]; int t=lca2(y,z); return work2(x,z)+work2(y,t)-f[t]+sa[x]+sa[y]-sa[z]-sa[fa[z][0]]; } void dfs2(int u) { per(i,n,1) { u=Q[i]; f[u]=0; for(int i=head[u]; i; i=Next[i]) if(v[i]!=fa[u][0])f[u]+=f[v[i]]; for(int i=head2[u]; i; i=Next2[i]) { int t=v2[i]; int x=q[t].x,y=q[t].y,z=q[t].z; f[u]=max(f[u],work(x,y,z)); } change(root,1,n,st[u],ed[u],f[u],0); change(root,1,n,st[fa[u][0]],ed[fa[u][0]],f[u],1); } } int main() { n=read(); rep(i,1,n)a[i]=read(); rep(i,2,n) { int x=read(),y=read(); add(x,y); add(y,x); } dfs(1); m=read(); rep(i,1,m)q[i].x=read(),q[i].y=read(),q[i].z=lca(q[i].x,q[i].y),add2(q[i].z,i); dfs2(1); cout<<f[1]<<endl; return 0; }
感觉不可做
想了较长时间T3,做了无用功