AcWing 1171. 距离 && AcWing 1172. 祖孙询问 牛客多校第一场 day33

今天div2睡过头了 呜呜 只好去学一下lca了

只做了三道多校 好像再一道就是期望dp了 不想写啊!(逃

A          Villages: Landlines

区间排序 然后再维护一个左边max

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
const int M = 1<<20;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
pair<int,int>p[N];
signed main(){
    fast
    int n;cin>>n;
    for(int i=0;i<n;i++){
        int a,b;cin>>a>>b;
        p[i].first=a-b;
        p[i].second=a+b;
    }
    sort(p,p+n);
    int ans=0,mx=p[0].second;
    for(int i=0;i<n-1;i++){
        if(p[i].second>mx)mx=p[i].second;
        if(p[i+1].first-mx>0)ans+=p[i+1].first-mx;
    }
    cout<<ans<<endl;
    return ~~(0^_^0);
}

D         Mocha and Railgun

一开始就一眼对的 然后跟队友讨论了一会 

不过还是学到很多!

睡之

(哦 对真的很简单 一行就秒了 )

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
const int M = 1<<20;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
double dis0(double x,double y){
    return sqrt(x*x+y*y);
}
signed main(){
    int t;cin>>t;
    while(t--){
        double R;cin>>R;
        double x,y,r;cin>>x>>y>>r;
        printf("%lf\n",R*abs(asin((dis0(x,y)-r)/R)-asin((dis0(x,y)+r)/R)));
    }
    return ~~(0^_^0);
}

我就说一行吧

G         Lexicographical Maximum

春春签到提吧

#include <bits/stdc++.h>
using namespace std;
const int N = 55;
const int M = 1<<20;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}

signed main(){
    fast
    string s;cin>>s;
    int flag=0;
    for(int i=0;i<s.size()-1;i++){
        if(s[i]!='9')flag=1;
    }
    if(s.size()==1)cout<<s[0]<<Endl;
    else{
        if(flag){
            for(int i=1;i<=s.size()-1;i++)cout<<9;
        }else{
            cout<<s<<endl;
        }
    }
    return ~~(0^_^0);
}

AcWing 1172. 祖孙询问

lca模板提啊!

先建图 根节点不用连

然后让根节点dfs all 把每个点的depth 和 fa【】【】预处理出来

fa这个数组我们才用递推 并且刷表的方式

下一步就直接求lca了 

不过今天我才学到了 二进制拼凑?这个东西 十分厉害啊

我们一定可以得到其临界情况 非常有用啊!并且log

#include <bits/stdc++.h>
using namespace std;
const int N = 4e4+10;
const int M = 1<<20;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int n,h[N],e[N<<1],ne[N<<1],idx,root,fa[N][16],depth[N],m;
void add(int a,int b){
    e[idx]=b;
    ne[idx]=h[a];
    h[a]=idx++;
}
void dfs(int x){
    memset(depth,0x3f3f,sizeof depth);
    queue<int>q;
    depth[0]=0,depth[x]=1;
    q.push(x);
    while(q.size()){
        auto t=q.front();q.pop();
        for(int i=h[t];~i;i=ne[i]){
            int j=e[i];
            if(depth[j]>depth[t]+1){
                depth[j]=depth[t]+1;
                fa[j][0]=t;
                q.push(j);
                for(int k=1;k<=15;k++){
                    fa[j][k]=fa[fa[j][k-1]][k-1];
                }
            }
        }
    }
}
int lca(int a,int b){
    if(depth[a]<depth[b])swap(a,b);
    for(int k=15;k>=0;k--)if(depth[fa[a][k]]>=depth[b])a=fa[a][k];
    if(a==b)return b;
    for(int k=15;k>=0;k--){
        if(fa[a][k]!=fa[b][k]){
            a=fa[a][k];
            b=fa[b][k];
        }
    }
    return fa[a][0];
}
signed main(){
    cin>>n;
    memset(h,-1,sizeof h);
    for(int i=1;i<=n;i++){
        int a,b;cin>>a>>b;
        if(b==-1)root=a;
        else add(a,b),add(b,a);
    }
    dfs(root);
    cin>>m;
    while(m--){
        int a,b;cin>>a>>b;
        if(lca(a,b)==a)cout<<1<<endl;
        else if(lca(a,b)==b)cout<<2<<endl;
        else cout<<0<<endl;
    }
    return ~~(0^_^0);
}

AcWing 1171. 距离

Tarjan这个做法是O(n+m)的 十分牛逼啊(不过离线

我们要先把询问存下来 可以用vector 这样查询就可以O1

然后预处理距离 这里我用的bfs 

(记得初始化 h 并查集

然后就是重头戏

我们递归的求每一个点是否有询问 要是有我们就把他搞到res里去

注意我们应该把询问放在递归的外面 就像st一样 可以将每个点都查询到 可以把头提出来 但是会多几行

#include <bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
const int M = 1<<20;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int n,m,h[N],e[N<<1],ne[N<<1],idx,w[N<<1],d[N<<1],p[N<<1],res[N<<1],st[N<<1];
bool st1[N<<1];
vector<pair<int,int>>v[N];
int find(int x){
    if(p[x]!=x)p[x]=find(p[x]);
    return p[x];
}
void add(int a,int b,int c){
    e[idx]=b;
    w[idx]=c;
    ne[idx]=h[a];
    h[a]=idx++;
}
void bfs(int x){
    queue<int>q;
    d[x]=0;st1[x]=1;
    q.push(x);
    while(q.size()){
        auto t=q.front();q.pop();
        for(int i=h[t];~i;i=ne[i]){
            int j=e[i];
            if(!st1[j]){
                d[j]=d[t]+w[i];
                st1[j]=1;
                q.push(j);
            }
        }
    }
}
void tarjan(int x){
    st[x]=1;
    for(int i=h[x];~i;i=ne[i]){
        int j=e[i];
        if(!st[j]){
            tarjan(j);
            for(auto item:v[j]){
                auto y=item.first,i=item.second;
                if(st[y]==2){
                    res[i]=d[y]+d[j]-2*d[find(y)];
                }
            }
            st[j]=2;
            p[j]=x;
        }
    }
}
signed main(){
    cin>>n>>m;
    memset(h,-1,sizeof h);
    for(int i=1;i<n;i++){
        int a,b,c;cin>>a>>b>>c;
        add(a,b,c),add(b,a,c);
    }
    for(int i=1;i<=n;i++)p[i]=i;
    bfs(1);
    for(int i=1;i<=m;i++){
        int a,b;cin>>a>>b;
        if(a!=b){
            v[a].push_back({b,i});
            v[b].push_back({a,i});
        }
    }
    tarjan(1);
    for(int i=1;i<=m;i++)cout<<res[i]<<endl;
    return ~~(0^_^0);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值