Educational Codeforces Round 132 (Rated for Div. 2)(C:贪心 Dst表 E启发式合并使每条路径异或和不为1)

B:普通前缀和即可

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10,M=2*N,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
using node=tuple<int,int,int>;
const long long inf=1e18;

int n,m,k;
int a[N];
int pre[N],suf[N];
void solve()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=n-1;i>=1;i--){
        pre[i]=pre[i+1];
        if(a[i]>=a[i+1])
        pre[i]+=a[i]-a[i+1];
    }
    for(int i=2;i<=n;i++){
        suf[i]=suf[i-1];
        if(a[i]>=a[i-1])
        suf[i]+=a[i]-a[i-1];
    }
    while(m--){
        int l,r;cin>>l>>r;
        if(l<r){
            cout<<pre[l]-pre[r]<<"\n";
        }else{
            cout<<suf[l]-suf[r]<<"\n";
        }
    }
}
//1 2 3 4
signed main()
{
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    int t=1;

    //cin>>t;

    while(t--) solve();
}

C:直接贪心,众所周知合法序列保证过程的权值要大于>=0即可,

特判如果过程中 cnt+now=1,now是负数,说明前面的cnt-1都要是(,当前问号只能做为(

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10,M=2*N,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
using node=tuple<int,int,int>;
const long long inf=1e18;

int n,m,k;
int a[N];

void solve()
{
    string s;cin>>s;
    int now=0,cnt=0;

    for(auto x:s){
        if(x=='(')
        {
            now++;
        }
        else if(x==')') now--;
        else if(x=='?'){
            cnt++;
        }
        if(cnt+now==1){
            now=1;
            cnt=0;
        }
    }
    if(abs(now)!=cnt) cout<<"NO\n";
    else
    cout<<"YES\n";
}
//1 2 3 4
signed main()
{
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    int t=1;

    cin>>t;

    while(t--) solve();
}

D:首先如果坐标差不是k的倍数就不行,然后直接贪心,让我起始点往下走往右再往上就行,

如果中间段最大值卡住就不行

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10,M=2*N,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
using node=tuple<int,int,int>;
const long long inf=1e18;

int n,m,k;
int a[N];
int f[N][35];
void init(){
    for(int i=0;i<=30;i++){
        for(int j=1;j+(1<<i)-1<=m;j++){
            if(!i) f[j][i]=a[j];
            else f[j][i]=max(f[j][i-1],f[j+(1<<i-1)][i-1]);
        }
    }
}
int query(int l,int r){
    int len=r-l+1;
    int k=log(len)/log(2);
    //x+(1<<k)-1=r
    return max(f[l][k],f[r-(1<<k)+1][k]);
}
void solve()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>a[i];
    }
    init();
    int q;cin>>q;
    while(q--)
    {
        int xs,ys,xf,yf,k;
        cin>>xs>>ys>>xf>>yf>>k;
        if(abs(xs-xf)%k || abs(ys-yf)%k){
            cout<<"NO\n";
            continue;
        }
        if(ys>yf){
            swap(ys,yf);
            swap(xs,xf);
        }
        int cnt=(n-xs)/k;
        xs+=cnt*k;
        if(query(ys,yf)<xs){
            cout<<"YES\n";
        }else cout<<"NO\n";
    }
}
//1 2 3 4
signed main()
{
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    int t=1;

    //cin>>t;

    while(t--) solve();
}

E:

因为让每个路径异或和都不为0,就是让每个子树的异或和不为0,

x到y的路径异或和= d[x]^d[y]^a[lca(x,y)]

启发式合并的时候判断是不是有重复的即可,如果重复直接改变根的权值,因为大小不变

所以可以直接在 2>>100次方放个1就行,

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10,M=2*N,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
using node=tuple<int,int,int>;
const long long inf=1e18;

int n,m,k;
int a[N];
vector<int> g[N];
int d[N];
set<int> st[N];
int res;
void dfs(int u,int fa)
{
       for(auto v:g[u]){
           if(v==fa) continue;
           d[v]=(a[v]^d[u]);
           dfs(v,u);
       }
}
void dfs1(int u,int fa){
    st[u].insert(d[u]);
    bool f=false;
    for(auto v:g[u])
    {
        if(v==fa) continue;
        dfs1(v,u);
        if(st[u].size()<st[v].size())
        {
            swap(st[u],st[v]);
        }
        for(auto k:st[v])
        {
            if(st[u].count(k^a[u]))
            {
                f=true;
            }
            //根:d[u]^d[v]^a[u]=0
            //路径=d[x]^d[y]^a[u]==0
        }
        for(auto k:st[v])
        st[u].insert((k));
    }
    if(f){
        res++;
        st[u].clear();
    }
}
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<n;i++){
        int x,y;cin>>x>>y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    res=0;
    d[1]=a[1];
    dfs(1,0);
    dfs1(1,0);
    cout<<res<<"\n";
}
//1 2 3 4
signed main()
{
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    int t=1;

    //cin>>t;

    while(t--) solve();
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值