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;
}

浙公网安备 33010602011771号