CF1153
CF1153A
按题意模拟即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
const int N=3e7+5;
const int M=1e5+5;
const int mod=1e7+9;
const int inf=0x3f3f3f3f;
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){x=-x;putchar('-');}
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('\n');}
int n,t,s,d,ans=inf,res;
signed main(){
n=read();t=read();
for(int i=1;i<=n;i++){
s=read();d=read();
while(s<t)s+=d;
if(s<ans)ans=s,res=i;
}
writel(res);
return 0;
}
CF1153B
诈骗题。想了 \(inf\) 种阶乘做法,发现对每个位置的答案就是该行/列的最大值取 \(\min\) /fn
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
const int N=1e2+5;
const int M=1e5+5;
const int mod=1e7+9;
const int inf=0x3f3f3f3f;
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){x=-x;putchar('-');}
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('\n');}
int n,m,h,a[N],b[N],vis[105][105];
signed main(){
n=read();m=read();h=read();
for(int i=1;i<=m;i++)a[i]=read();
for(int i=1;i<=n;i++)b[i]=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(read())vis[i][j]=min(b[i],a[j]);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
writei(vis[i][j]);
puts("");
}
return 0;
}
CF1153C
黄题调不出来。
显然的贪心做法:尽量在前面放左括号。
设 \(ans\) 表示 \([1,i]\) 中左括号比右括号多的个数。
前 \(n-1\) 位置要求 \(ans\le 0\) 第 \(n\) 位要求 \(ans=0\)
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
const int N=1e6+5;
const int M=1e5+5;
const int mod=1e7+9;
const int inf=0x3f3f3f3f;
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){x=-x;putchar('-');}
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('\n');}
int n,ans[N];
string s;
signed main(){
n=read();cin>>s;
if(n&1){puts(":(");return 0;}
int cnt=n>>1;
for(int i=0;i<=n-1;i++){
if(s[i]=='(')ans[i]++,cnt--;
if(s[i]==')')ans[i]--;
}
if(cnt<0){puts(":(");return 0;}
for(int i=0;i<=n-2;i++){
if(s[i]=='?')
if(cnt)s[i]='(',ans[i]++,cnt--;
else s[i]=')',ans[i]--;
if(i)ans[i]+=ans[i-1];
if(ans[i]<=0){puts(":(");return 0;}
}
if(s[n-1]=='?')
if(cnt)s[n-1]='(',ans[n-1]++,cnt--;
else s[n-1]=')',ans[n-1]--;
ans[n-1]+=ans[n-2];
if(ans[n-1])puts(":(");
else cout<<s<<endl;
return 0;
}
CF1153D
神仙树形dp。
先举个栗子:假如说一个点连着5个叶子 那么它的 \(\min\) 一定为1 \(\ \max\) 一定为5
对于 \(\min\) 和 \(\max\) 操作 我们能发现一些性质:
对 \(\min\) 操作 该节点答案相当于叶子总数量-所有叶子数+1(因为这样只能从大到小排了) 相当于取到所有叶子
对 \(\max\) 操作 该节点答案则为叶子总数量 这时我们发现它相当只取一个叶子
设 \(f_x\) 表示节点 \(x\) 连接的叶子总数量 每个节点的答案 \(ans\) 为 子树内所有叶子数-\(f_x+1\)
那么有如下转移:
解释一下 \(\min\) 操作 相当于儿子连的所有叶子 从大到小排
对 \(\max\) 操作 我们只连一个儿子 那么自然取最少的连了
边界条件:叶子节点 \(f_x=1\)
懒得建树 代码为非递归写法
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
const int N=1e6+5;
const int M=1e5+5;
const int mod=1e7+9;
const int inf=0x3f3f3f3f;
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){x=-x;putchar('-');}
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('\n');}
int n,a[N],fa[N],f[N],son[N],k,q[N],h,t=1;
string s;
signed main(){
n=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n;i++)f[i]=a[i]*inf;
for(int i=2;i<=n;i++)fa[i]=read();
for(int i=2;i<=n;i++)son[fa[i]]++;
for(int i=1;i<=n;i++)k+=!son[i];
for(int i=1;i<=n;i++)if(!son[i])q[++h]=i,f[i]=1;
while(h>=t){
int x=q[t++];
if(a[fa[x]])f[fa[x]]=min(f[fa[x]],f[x]);
else f[fa[x]]+=f[x];
if(!--son[fa[x]])q[++h]=fa[x];
}
writel(k-f[1]+1);
return 0;
}
CF1153E
交互题。
一个重要的性质:交互的答案如果为奇数 那么说明链的两个端点一个在矩形内 一个在矩形外
那么我们就可以用这个判定出每一行每一列是否存在一个端点 如果找到了二分确定具体位置
最多交互次数:\(n\times n\times \left\lceil\\log n\right\rceil\times \left\lceil\\log n\right\rceil\)
\(n=1000\) 时 次数为 \(2020\)
然后刚好多一。
我们在判行和列的时候 发现如果前 \(n-1\) 个里面找到了一个端点 那么 \(n\) 一定为另一个端点
那么我们的交互次数就只有 \(2018\) 次了
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
const int N=1e6+5;
const int M=1e5+5;
const int mod=1e7+9;
const int inf=0x3f3f3f3f;
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){x=-x;putchar('-');}
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('\n');}
int n,x,res;
vector<int>v;
signed main(){
n=read();
for(int i=1;i<n;i++){
printf("? %d %d %d %d\n",i,1,i,n);
fflush(stdout);
x=read();
if(x&1)v.push_back(i);
}
if(v.size()==1)v.push_back(n);
if(v.empty()){
for(int i=1;i<n;i++){
printf("? %d %d %d %d\n",1,i,n,i);
fflush(stdout);
x=read();
if(x&1)v.push_back(i);
}
if(v.size()==1)v.push_back(n);
int l=1,r=n,ans;
while(l<=r){
int mid=l+r>>1;
printf("? %d %d %d %d\n",l,v[0],mid,v[0]);
fflush(stdout);
x=read();
if(x&1)ans=mid,r=mid-1;
else l=mid+1;
}
res=ans;
l=1,r=n;
while(l<=r){
int mid=l+r>>1;
printf("? %d %d %d %d\n",l,v[1],mid,v[1]);
fflush(stdout);
x=read();
if(x&1)ans=mid,r=mid-1;
else l=mid+1;
}
printf("! %d %d %d %d\n",res,v[0],ans,v[1]);
fflush(stdout);
return 0;
}
int l=1,r=n,ans;
while(l<=r){
int mid=l+r>>1;
printf("? %d %d %d %d\n",v[0],l,v[0],mid);
fflush(stdout);
x=read();
if(x&1)ans=mid,r=mid-1;
else l=mid+1;
}
res=ans;
l=1,r=n;
while(l<=r){
int mid=l+r>>1;
printf("? %d %d %d %d\n",v[1],l,v[1],mid);
fflush(stdout);
x=read();
if(x&1)ans=mid,r=mid-1;
else l=mid+1;
}
printf("! %d %d %d %d\n",v[0],res,v[1],ans);
fflush(stdout);
return 0;
}
CF1153F
不会期望。