CF567
CF567A
在最小点和最大点之间选即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define endl '\n'
#define gc cin.get
#define pc cout.put
const int N=1e5+5;
const int M=1e7+5;
const int inf=0x7fffffff;
const int mod=997;
const int base=13131;
inl int read(){
int x=0,f=1;char c=gc();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x*f;
}
inl void write(int x){
if(x<0){pc('-');x=-x;}
if(x>9)write(x/10);
pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,a[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
n=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n;i++){
int x=min(i^1?a[i]-a[i-1]:inf,i^n?a[i+1]-a[i]:inf),y=max(a[i]-a[1],a[n]-a[i]);
cout<<x<<' '<<y<<endl;
}
return 0;
}
CF567B
按提议模拟,动态维护人数,对于凭空冒出来的人,把他当成一开始就在,最大值+1即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define endl '\n'
#define gc cin.get
#define pc cout.put
const int N=1e6+5;
const int M=1e7+5;
const int inf=0x7fffffff;
const int mod=997;
const int base=13131;
inl int read(){
int x=0,f=1;char c=gc();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x*f;
}
inl void write(int x){
if(x<0){pc('-');x=-x;}
if(x>9)write(x/10);
pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,a[N],res,t[N],now;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
n=read();
for(int i=1;i<=n;i++){
char c;cin>>c;
if(c=='+')t[read()]=1,now++;
else{
int x=read();
if(!t[x])res++;
else t[x]=0,now--;
}
res=max(res,now);
}
cout<<res<<endl;
return 0;
}
CF567C
开两个map维护前两个信息即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define int ll
#define endl '\n'
#define gc cin.get
#define pc cout.put
const int N=1e6+5;
const int M=1e7+5;
const int inf=0x7fffffff;
const int mod=997;
const int base=13131;
inl int read(){
int x=0,f=1;char c=gc();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x*f;
}
inl void write(int x){
if(x<0){pc('-');x=-x;}
if(x>9)write(x/10);
pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,k,a[N],res;
map<int,int>f,g;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
n=read();k=read();
for(int i=1;i<=n;i++){
a[i]=read();
if(!(a[i]%(k*k)))
if(g.find(a[i]/(k*k))!=g.end())res+=g[a[i]/(k*k)];
if(!(a[i]%k))
if(f.find(a[i]/k)!=f.end())g[a[i]/k]+=f[a[i]/k];
f[a[i]]++;
}
cout<<res<<endl;
return 0;
}
CF567D
开multiset维护每个连续段。
可以发现,对于长度为 \(k\) 的段,能放置的数量为 \(\lfloor\cfrac{k+1}{a+1}\rfloor\)
然后炮轰的段拆成两部分,重算贡献即可。
注意set按左端点排序后 两个左端点相同的块无法共存 所以用multiset
CF567E
从起点/终点各跑一遍dij,同时维护到达每个点的路径数。
然后对于每条边 \(u->v\),
如果 \(dis_{s->u}+w_i+dis_{v->t}==最短路\) 且 \(cnt_{s->u}*cnt_{v->t}==tot\) 答案 yes
否则看能否通过减边权使 \(dis_{s->u}+w_i+dis_{v->t}<最短路\) 判断剩下情况。
注意方案数很大,需要取模。听说1e9+7被卡了?
另一种做法:抽离出所有可能是最短路的边,求出割边,这样的边一定是Yes
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define int ll
#define endl '\n'
#define gc cin.get
#define pc cout.put
const int N=2e5+5;
const int M=1e7+5;
const int inf=0x7fffffff;
const int mod=998244353;
const int base=13131;
inl int read(){
int x=0,f=1;char c=gc();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x*f;
}
int n,m,s,t,dis1[N],dis2[N],vis[N],cnt1[N],cnt2[N],pre[N],flag[N];
struct edge{
int u,v,c;
}e[N];
int head[N],nxt[N],to[N],w[N],cnt;
inl void add(int u,int v,int c){
nxt[++cnt]=head[u];
to[cnt]=v;w[cnt]=c;
head[u]=cnt;
}
inl void dij(int s,int* dis,int* cnt){
memset(dis,0x3f,sizeof dis1);
memset(vis,0,sizeof vis);
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
q.push({0,s});dis[s]=0;cnt[s]=1;
while(!q.empty()){
int x=q.top().second;q.pop();
if(vis[x])continue;vis[x]=1;
for(int i=head[x];i;i=nxt[i]){
int y=to[i],c=w[i];
if(dis[y]==dis[x]+c)cnt[y]=(cnt[x]+cnt[y])%mod;
if(dis[y]>dis[x]+c){
cnt[y]=cnt[x];
dis[y]=dis[x]+c;
q.push({dis[y],y});
}
}
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
n=read();m=read();s=read();t=read();
for(int i=1;i<=m;i++)e[i]={read(),read(),read()};
for(int i=1;i<=m;i++)
add(e[i].u,e[i].v,e[i].c);
dij(s,dis1,cnt1);
memset(head,0,sizeof head);
memset(nxt,0,sizeof nxt);
cnt=0;
for(int i=1;i<=m;i++)
add(e[i].v,e[i].u,e[i].c);
dij(t,dis2,cnt2);
for(int i=1;i<=m;i++){
int u=e[i].u,v=e[i].v,c=e[i].c;
if(dis1[u]+c+dis2[v]==dis1[t]&&cnt1[u]*cnt2[v]%mod==cnt1[t])cout<<"YES"<<endl;
else{
int ans=dis1[u]+c+dis2[v]-dis1[t]+1;
if(ans>c-1)cout<<"NO"<<endl;
else cout<<"CAN"<<' '<<ans<<endl;
}
}
return 0;
}
CF567F
设 \(f_{l,r}\) 表示填完 \([1,l]\) \([r,2n]\) 的方案数。
可以从 \(f_{l-2,r}/f_{l-1,r-1}/f_{l,r-2}\) 转移,多出来的两位填一个数。
没填的一定比他们大,填完的一定比他们小,根据大小判断能否转移。
实现细节很多。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define int ll
#define endl '\n'
#define gc cin.get
#define pc cout.put
const int N=2e2+5;
const int M=1e7+5;
const int inf=0x7fffffff;
const int mod=998244353;
const int base=13131;
inl int read(){
int x=0,f=1;char c=gc();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x*f;
}
int n,m,f[N][N];
struct node{
int op,to;
};
vector<node>v[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
n=read();m=read();
while(m--){
int x,y,op;string s;
cin>>x>>s>>y;
if(s==">")op=0;
if(s=="<")op=1;
if(s==">=")op=2;
if(s=="<=")op=3;
if(s=="=")op=4;
v[x].push_back({op,y});
v[y].push_back({op^1,x});
}
f[0][n<<1|1]=1;
for(int i=2;i<=n<<1;i+=2){
for(int l=0,r=(n<<1)-i+1;r<=(n<<1|1);l++,r++){
if(l&&r){
int flag=1,pos1=l,pos2=r;
for(auto k:v[pos1]){
int op=k.op,y=k.to;
if(op==0&&pos1<=y&&y<=pos2)flag=0;
if(op==1&&(y<=pos1||y>=pos2))flag=0;
if(op==2&&pos1<y&&y<pos2)flag=0;
if(op==3&&(y<pos1||y>pos2))flag=0;
if(op>=4&&(y^pos1&&y^pos2))flag=0;
}
for(auto k:v[pos2]){
int op=k.op,y=k.to;
if(op==0&&pos1<=y&&y<=pos2)flag=0;
if(op==1&&(y<=pos1||y>=pos2))flag=0;
if(op==2&&pos1<y&&y<pos2)flag=0;
if(op==3&&(y<pos1||y>pos2))flag=0;
if(op>=4&&(y^pos1&&y^pos2))flag=0;
}
f[l][r]+=flag*f[l-1][r+1];
}
if((n<<1)-r+1>=2){
int flag=1,pos1=r+1,pos2=r;
for(auto k:v[pos1]){
int op=k.op,y=k.to;
if(op==0&&l+1<=y&&y<=r+1)flag=0;
if(op==1&&(y<l+1||y>r-1))flag=0;
if(op==2&&l+1<=y&&y<=r-1)flag=0;
if(op==3&&(y<l+1||y>r+1))flag=0;
if(op>=4&&(y^pos1&&y^pos2))flag=0;
}
for(auto k:v[pos2]){
int op=k.op,y=k.to;
if(op==0&&l+1<=y&&y<=r+1)flag=0;
if(op==1&&(y<l+1||y>r-1))flag=0;
if(op==2&&l+1<=y&&y<=r-1)flag=0;
if(op==3&&(y<l+1||y>r+1))flag=0;
if(op>=4&&(y^pos1&&y^pos2))flag=0;
}
f[l][r]+=flag*f[l][r+2];
}
if(l>=2){
int flag=1,pos1=l-1,pos2=l;
for(auto k:v[pos1]){
int op=k.op,y=k.to;
if(op==0&&l-1<=y&&y<=r-1)flag=0;
if(op==1&&(y<l+1||y>r-1))flag=0;
if(op==2&&l+1<=y&&y<=r-1)flag=0;
if(op==3&&(y<l-1||y>r-1))flag=0;
if(op>=4&&(y^pos1&&y^pos2))flag=0;
}
for(auto k:v[pos2]){
int op=k.op,y=k.to;
if(op==0&&l-1<=y&&y<=r-1)flag=0;
if(op==1&&(y<l+1||y>r-1))flag=0;
if(op==2&&l+1<=y&&y<=r-1)flag=0;
if(op==3&&(y<l-1||y>r-1))flag=0;
if(op>=4&&(y^pos1&&y^pos2))flag=0;
}
f[l][r]+=flag*f[l-2][r];
}
}
}
int ans=0;
for(int i=0;i<=n<<1;i++)ans+=f[i][i+1];
cout<<ans/3<<endl;
return 0;
}