T1 usaco20feb Equilateral Triangles P
题面我就不描述了
题解
首先我们是不可能暴力计算每一对点距离的
我们可以想一想如何将斜着的数个点转换为横着或竖着的数个点,这样会使我们的计算方便许多
不难想到的是切比雪夫距离,当然考场上也容易推出这玩意(我就是考场现推的)
然后就是如何统计
对于一个点对,我们只需要知道这两个点间的距离,并这个距离的两倍分别作两个正方形,两个正方形的中心点分别是你所选的两个点
不难发现对于两个正方形会有重叠的部分(只考虑边,不考虑面积),在重叠部分上面的点与两个点的距离是相等的
那么上面的点与这两个点都可以构成正方形
统计前缀和数组来维护一下就好了(注意边界点)
代码如下
#include<bits/stdc++.h>
using namespace std;
int n,a[610][610],ans,suma[610][610],sumb[610][610];
int main(){
scanf("%d",&n);
for(int i = 1;i<=n;i++){
string s;cin>>s;
for(int j = 1;j<=n;j++) if(s[j-1]=='*') a[i+j][i-j+n] = 1;
}
n*=2;
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
suma[i][j] = suma[i][j-1]+a[i][j];
sumb[i][j] = sumb[i-1][j]+a[i][j];
}
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
if(a[i][j]==0) continue;
for(int k = j+1;k<=n;k++){
if(a[i][k]==0) continue;
int tmp = i+k-j;
if(tmp<=n)ans+=suma[tmp][k]-suma[tmp][j-1];
tmp = i-k+j;
if(tmp>0)ans+=suma[tmp][k]-suma[tmp][j-1];
}
}
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
if(a[j][i]==0) continue;
for(int k = j+1;k<=n;k++){
if(a[k][i]==0) continue;
int tmp = i+k-j;
if(tmp<=n)ans+=sumb[k-1][tmp]-sumb[j][tmp];
tmp = i-k+j;
if(tmp>0)ans+=sumb[k-1][tmp]-sumb[j][tmp];
}
}
}
printf("%d",ans);
return 0;
}
T2 换公路
题解
首先很明显的是这一定是两棵树
如果两条边 \(e_1,e_2\) 在两棵树 \(T_1,T_2\) 中可以互相替代,则 \(e_2\) 在 \(T_2\) 中 \(e_1\) 两端点的路径上,\(e_1\) 在 \(T_1\) 中 \(e_2\) 两端点的路径上
那么先把 \(T_2\) 的每条边在 \(T_1\) 上差分,也就是在两端点处插入这条边, 在 \(lca\) 处删除这条边
考虑每条边时只考虑在子树中有的边,现在只需要考虑支持诸如加入/删除一个点到集合中,查询一条路径能覆盖集合中的几个点即可
查询可利用利用 dfs 序 + 线段树,合并子树采用线段树合并
时间复杂度 \(\mathcal{O} (n log n)\)
码量挺大
#include<bits/stdc++.h>
#define N 500100
using namespace std;
struct node{
int l,r,s;
}t[N<<6];
vector<int>ve[N];
int n,tot,sz,in[N],out[N],rt[N],ans[N];
struct Tree{
struct edge{
int v,ne;
}e[N<<1];
int cnt,h[N],fa[N],dep[N],siz[N],top[N];
void add(int u,int v){
e[++cnt].v = v;
e[cnt].ne = h[u];
h[u] = cnt;
e[++cnt].v = u;
e[cnt].ne = h[v];
h[v] = cnt;
}
void dfs1(int x){
dep[x] = dep[fa[x]]+1;
siz[x] = 1;
for(int i = h[x];i;i = e[i].ne){
int v = e[i].v;
if(v==fa[x]) continue;
fa[v] = x;
dfs1(v);
siz[x]+=siz[v];
}
}
void dfs2(int x,int ch){
top[x] = ch;
int k = 0;
for(int i = h[x];i;i = e[i].ne){
int v = e[i].v;
if(v!=fa[x]&&siz[v]>siz[k])
k = v;
}
if(k) dfs2(k,ch);
for(int i = h[x];i;i = e[i].ne){
int v = e[i].v;
if(v!=fa[x]&&v!=k)
dfs2(v,v);
}
}
void dfs3(int x){
in[x] = ++tot;
for(int i = h[x];i;i = e[i].ne){
int v = e[i].v;
if(v!=fa[x])
dfs3(v);
}
out[x] = ++tot;
}
int get_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;
}
}t1,t2;
int newnode(){
sz++;
t[sz].l = t[sz].r = t[sz].s = 0;
return sz;
}
int merge(int x,int y){
if(!x||!y) return x+y;
t[x].s+=t[y].s;
t[x].l = merge(t[x].l,t[y].l);
t[x].r = merge(t[x].r,t[y].r);
return x;
}
void modify(int &d,int l,int r,int x,int y){
if(!d) d = newnode();
t[d].s+=y;
if(l==r) return ;
int mid = (l+r)>>1;
if(x<=mid) modify(t[d].l,l,mid,x,y);
else modify(t[d].r,mid+1,r,x,y);
}
int query(int d,int l,int r,int x,int y){
if(!d||(x<=l&&r<=y)) return t[d].s;
int mid = (l+r)>>1,res = 0;
if(x<=mid) res+=query(t[d].l,l,mid,x,y);
if(y>mid) res+=query(t[d].r,mid+1,r,x,y);
return res;
}
void solve(int x){
for(int i = t2.h[x];i;i = t2.e[i].ne){
int v = t2.e[i].v;
if(v==t2.fa[x]) continue;
solve(v);
rt[x] = merge(rt[x],rt[v]);
}
for(int i = 0;i<(int)ve[x].size();i++){
int y = ve[x][i];
if(y>0){
modify(rt[x],1,tot,in[y],1);
modify(rt[x],1,tot,out[y],-1);
}else{
modify(rt[x],1,tot,in[-y],-2);
modify(rt[x],1,tot,out[-y],2);
}
}
if(x==1) return ;
int lca = t1.get_lca(x,t2.fa[x]);
ans[x] = query(rt[x],1,tot,1,in[x])+query(rt[x],1,tot,1,in[t2.fa[x]])-2*query(rt[x],1,tot,1,in[lca]);
}
int main(){
scanf("%d",&n);
for(int i = 1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
t2.add(x,y);
}
for(int i = 1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
t1.add(x,y);
}
t1.dfs1(1);
t1.dfs2(1,1);
t1.dfs3(1);
t2.dfs1(1);
t2.dfs2(1,1);
for(int i = 1;i<n*2-1;i+=2){
int x = t1.e[i].v,y = t1.e[i+1].v,lca = t2.get_lca(x,y);
if(t1.dep[x]<t1.dep[y]) swap(x,y);
ve[x].push_back(x);
ve[y].push_back(x);
ve[lca].push_back(-x);
}
solve(1);
for(int i = 1;i<n*2-1;i+=2){
int x = t2.e[i].v,y = t2.e[i+1].v;
if(t2.dep[x]<t2.dep[y])
swap(x,y);
printf("%d ",ans[x]);
}
return 0;
}
T3 cf1335f
同样自己看题意
题解
洛谷题解已经讲的很好了,我就不献丑了
#include<bits/stdc++.h>
#define N 1000010
using namespace std;
int n,m,t,ne[30][N];
char dis[N],col[N];
bool have[3][N];
string s;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i = 1;i<=n*m;i++)
have[1][i] = have[0][i] = false;
for(int i = 1;i<=n;i++){
cin>>s;
for(int j = 1;j<=m;j++)
col[(i-1)*m+j] = s[j-1];
}
for(int i = 1;i<=n;i++){
cin>>s;
for(int j = 1;j<=m;j++)
dis[(i-1)*m+j] = s[j-1];
}
for(int i = 1;i<=n*m;i++){
switch(dis[i]){
case'U':ne[0][i] = i-m;break;
case'D':ne[0][i] = i+m;break;
case'L':ne[0][i] = i-1;break;
case'R':ne[0][i] = i+1;break;
}
}
for(int i = 1;i<=20;i++)
for(int j = 1;j<=n*m;j++)
ne[i][j] = ne[i-1][ne[i-1][j]];
for(int i = 1;i<=n*m;i++){
int tmp = i;
for(int j = 20;~j;j--){
if((n*m>>j)&1) tmp = ne[j][tmp];
}
have[col[i]^48][tmp] = true;
}
int bla = 0,ans = 0;
for(int i = 1;i<=n*m;i++){
if(have[0][i]) ans++,bla++;
else if(have[1][i]) ans++;
}
printf("%d %d\n",ans,bla) ;
}
return 0;
}
T4 找宝藏
题解
有点迷糊,就不误导大家了
#include<bits/stdc++.h>
#define N 100010
#define ll long long
#define INF (ll)(0x3f3f3f3f3f3f3f3f)
using namespace std;
int n,m,deg[N],v[N][40];
ll cnt,siz[N],s[N][40];
vector<int>son[N],fa[N];
vector<ll>sum[N];
queue<int>q;
int getson(int u,int d){
if(!d) return u;
for(int i = 30;~i;i--)
if((v[u][i])&&(siz[v[u][i]]+s[u][i]>=d)&&(s[u][i]<=d))
return getson(v[u][i],d-s[u][i]);
int p = (--lower_bound(sum[u].begin(),sum[u].end(),d))-sum[u].begin();
return getson(son[u][p+1],d-(~p?sum[u][p]:0)-1);
}
int main(){
scanf("%d%d",&n,&m);
for(int i = 1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
deg[x]++;
son[x].push_back(y);
fa[y].push_back(x);
}
for(int i = 1;i<=n;i++)
if(!deg[i]) q.push(i);
while(q.size()){
cnt++;
int u = q.front();q.pop();
for(int i = 0;i<son[u].size();i++){
siz[u]+=(siz[son[u][i]]+1);
siz[u] = min(siz[u],INF);
sum[u].push_back(siz[u]);
}
if(son[u].size()){
int p = 0;
for(int i = 1;i<son[u].size();i++)
if(siz[son[u][i]]>siz[son[u][p]]) p = i;
s[u][0] = 1;
v[u][0] = son[u][p];
for(int i = 0;i<p;i++){
s[u][0]+=siz[son[u][i]]+1;
s[u][0] = min(s[u][0],INF);
}
for(int i = 1;i<=30;i++){
v[u][i] = v[v[u][i-1]][i-1];
if(!v[u][i]) break;
s[u][i] = s[u][i-1]+s[v[u][i-1]][i-1];
s[u][i] = min(s[u][i],INF);
}
}
for(int i = 0;i<fa[u].size();i++){
int v = fa[u][i];
if(!(--deg[v])) q.push(v);
}
}
int q;
scanf("%d",&q);
for(int i = 1;i<=q;i++){
int x,k;
scanf("%d%d",&x,&k);
if(siz[x]<k) puts("-1");
else printf("%d\n",getson(x,k));
}
return 0;
}
标签:rt,tmp,校内,int,t2,tot,230719,ans
From: https://www.cnblogs.com/cztq/p/17662945.html