CF1401

CF1401A

题意:在数抽上给出点 \(A\) 求存在点 \(B\) 满足 \(\left|\operatorname{dist}(O,B) - \operatorname{dist}(A,B) \right| = k\) \(\ A\) 的最小移动次数

显然 \(\left|\operatorname{dist}(O,B) - \operatorname{dist}(A,B) \right| = k\) 的最大值为 \(\operatorname{dist}(O,A)\)

那么 \(n<k\) 时 把 \(n\) 加到 \(k\)

那么我们就有:\(\begin{cases}\operatorname{dist}(O,B) - \operatorname{dist}(A,B) = k\\\operatorname{dist}(O,B) + \operatorname{dist}(A,B) = n\end{cases}\)

显然 \(n+k\) 为偶数时有解 特判一下

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define inl inline
#define ll long long 
#define endl '\n'
const int N=1e6+5;
const int M=1e5+5;
const int inf=0x3f3f3f3f;
const int base=131;
const int mod=998244853;
inl int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
inl void write(int x){
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar(endl);}
bool st;
int t,n,k,ans;
bool ed;
signed main(){
    t=read();
    while(t--){
        n=read();k=read();
        ans=(n<k?k-n:0);
        if(n<k)n=k;
        ans+=((n+k)&1);
        writel(ans);
    }
    return 0;
}

CF1401B

显然 只有 \(z1、y2\) 会产生正贡献 \(z2、y1\) 会产生负贡献 剩下全是0

直接贪就行

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define inl inline
#define ll long long 
#define endl '\n'
const int N=1e6+5;
const int M=1e5+5;
const int inf=0x3f3f3f3f;
const int base=131;
const int mod=998244853;
inl int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
inl void write(int x){
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar(endl);}
bool st;
int t,x,y,z,xx,yy,zz,ans;
bool ed;
signed main(){
    t=read();
    while(t--){
        x=read();y=read();z=read();
        xx=read();yy=read();zz=read();
        ans=min(z,yy)*2;
        z-=min(z,yy),yy-=min(z,yy);
        zz-=min(zz,x);zz-=min(zz,z);
        ans-=zz*2;
        writel(ans);
    }
    return 0;
}

CF1401C

设最小的数为 \(a_k\)

那么只要满足 \(a_k|a_i\) 他俩就能交换位置

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define inl inline
#define ll long long 
#define endl '\n'
const int N=1e6+5;
const int M=1e5+5;
const int inf=0x3f3f3f3f;
const int base=131;
const int mod=998244853;
inl int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
inl void write(int x){
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar(endl);}
bool st;
int t,n,a[N],b[N];
bool ed;
inl int gcd(int a,int b){return !b?a:gcd(b,a%b);}
signed main(){
    t=read();
    while(t--){
        n=read();
        for(int i=1;i<=n;i++)a[i]=b[i]=read();
        sort(b+1,b+n+1);int flag=1;
        for(int i=1;i<=n;i++){
            if(b[i]==a[i])continue;
            if(a[i]%b[1]){flag=0;break;}
        }
        puts(flag?"YES":"NO");
    }
    return 0;
}

CF1401D

一个套路的想法 考虑每条边的贡献 答案为 \(\sum siz_y*(n-siz_y)*w_i\)

\(w_i\) 就是那些质数

对于 \(m\le n-1\) 在前面填1

对于 \(m>n-1\) 把多出来的质数都乘到第 \(n-1\) 个上

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define inl inline
#define ll long long 
#define endl '\n'
#define int ll
const int N=2e5+5;
const int M=1e5+5;
const int inf=0x3f3f3f3f;
const int base=131;
const int mod=1e9+7;
inl int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
inl void write(int x){
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar(endl);}
bool st;
int t,n,u,v,siz[N],m,ans;
int head[N],nxt[N],to[N],cnt;
inl void add(int u,int v){
    nxt[++cnt]=head[u];
    to[cnt]=v;
    head[u]=cnt;
}
vector<int>ve,p;
bool ed;
inl void init(){
    memset(head,0,sizeof head);
    memset(nxt,0,sizeof nxt);
    cnt=ans=0;ve.clear();p.clear();
}
inl void dfs(int x,int fa){
    siz[x]=1;
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(y==fa)continue;
        dfs(y,x);
        siz[x]+=siz[y];
        ve.push_back(siz[y]*(n-siz[y]));
    }
}
signed main(){
    t=read();
    while(t--){
        n=read();init();
        for(int i=1;i<=n-1;i++){
            u=read();v=read();
            add(u,v);add(v,u);
        }
        dfs(1,0);
        sort(ve.begin(),ve.end());
        m=read();
        for(int i=1;i<=m;i++)p.push_back(read());
        for(;m<n-1;m++)p.push_back(1);
        sort(p.begin(),p.end());
        for(int i=n-1;i<p.size();i++)
            p[n-2]=p[n-2]*p[i]%mod;
        for(int i=0;i<=n-2;i++)ans=(ans+ve[i]%mod*(p[i]%mod)%mod)%mod;
        writel(ans);
    }
    return 0;
}

CF1401E

经典猜不出结论。

\(ans=\)线段交点数+长为1e6的线段数+1

感性理解 有一个交点就圈出一个长方形 一个1e6的线段就堵死了答案也会+1 最后算上切剩下的

树状数组+扫描线即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define inl inline
#define ll long long 
#define endl '\n'
#define int ll
const int N=1e6+5;
const int M=1e5+5;
const int inf=0x3f3f3f3f;
const int base=131;
const int mod=1e9+7;
inl int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
inl void write(int x){
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar(endl);}
bool st;
int t,n,m,l,r,x,y,cnt,ans,a[N];
struct node{
    int op,x,v,h;
    friend bool operator<(node a,node b){return a.h^b.h?a.h<b.h:a.op<b.op;}
}q[N];
inl void add(int x,int v){
    for(;x<=1e6+1;x+=x&-x)a[x]+=v;
}
inl int query(int x){
    int ans=0;
    for(;x;x-=x&-x)ans+=a[x];
    return ans;
}
bool ed;
signed main(){
    n=read();m=read();
    for(int i=1;i<=n;i++){
        y=read();l=read();r=read();
        ans+=(r-l==(int)1e6);
        q[++cnt]={0,l+1,1,y};
        q[++cnt]={0,r+2,-1,y};
    }
    for(int i=1;i<=m;i++){
        x=read();l=read();r=read();
        ans+=(r-l==(int)1e6);
        q[++cnt]={1,x+1,-1,l-1};
        q[++cnt]={1,x+1,1,r};
    }
    sort(q+1,q+cnt+1);
    for(int i=1;i<=cnt;i++){
        if(!q[i].op)add(q[i].x,q[i].v);
        else ans+=query(q[i].x)*q[i].v;
    }
    writel(ans+1);
    return 0;
}

CF1401E

ds题。

首先14操作显然是树状数组/线段树的传统艺能

发现不好搞的23操作 影响的区间长度都是 \(2^k\) 容易想到线段树

以下称线段树区间长度为 \(2^k\) 的一层为第 \(k\)

发现3操作相当于使整个线段树第 \(k\) 层左右儿子交换位置 2操作则是 让 \(k-1\) 到第 \(0\) 层全交换位置

我们打个tag即可

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define inl inline
#define ll long long 
#define endl '\n'
#define int ll
#define ls k<<1
#define rs k<<1|1
#define mid (l+r>>1)
const int N=3e5+5;
const int M=1e5+5;
const int inf=0x3f3f3f3f;
const int base=131;
const int mod=1e9+7;
inl int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
inl void write(int x){
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar(endl);}
bool st;
int t,n,m,a[N],op,x,k,l,r;
bool ed;
struct segtree{
    int s[N<<2],rev[N<<2];
    inl void pushup(int k){s[k]=s[ls]+s[rs];}
    inl void build(int k,int l,int r){
        if(l==r)return s[k]=a[l],void();
        build(ls,l,mid);build(rs,mid+1,r);
        pushup(k);
    }
    inl void modify(int k,int dep,int l,int r,int x,int v){
        if(l==r)return s[k]=v,void();
        if(!rev[dep-1]){
            if(x<=mid)modify(ls,dep-1,l,mid,x,v);
            else modify(rs,dep-1,mid+1,r,x,v);
        }else{
            if(x<=mid)modify(rs,dep-1,l,mid,x,v);
            else modify(ls,dep-1,mid+1,r,x,v);
        }
        pushup(k);
    }
    inl int query(int k,int dep,int l,int r,int x,int y){
        if(x<=l&&r<=y)return s[k];
        int ans=0;
        if(!rev[dep-1]){
            if(x<=mid)ans+=query(ls,dep-1,l,mid,x,y);
            if(y>mid)ans+=query(rs,dep-1,mid+1,r,x,y);
        }else{
            if(x<=mid)ans+=query(rs,dep-1,l,mid,x,y);
            if(y>mid)ans+=query(ls,dep-1,mid+1,r,x,y);
        }
        return ans;
    }
}SGT;
signed main(){
    n=read();m=read();
    for(int i=1;i<=(1<<n);i++)a[i]=read();
    SGT.build(1,1,1<<n);
    while(m--){
        op=read();
        switch(op){
            case 1:
                x=read();k=read();
                SGT.modify(1,n,1,1<<n,x,k);
                break;
            case 2:
                k=read();
                for(int i=k-1;~i;i--)SGT.rev[i]^=1;
                break;
            case 3:
                k=read();
                SGT.rev[k]^=1;
                break;
            default:
                l=read();r=read();
                writel(SGT.query(1,n,1,1<<n,l,r));
                break;
        }
    }
    return 0;
}
posted @ 2023-11-20 14:58  xiang_xiang  阅读(39)  评论(0)    收藏  举报