版权声明:这是蒟蒻的BLOG,神犇转载也要吱一声哦~ https://blog.csdn.net/Dream_Lolita/article/details/85239751
【前言】
并不能打div2的我十分绝望。
虽然上分了还是很高兴。
【题目】
原题地址
A.Connect Three
将三个格子按 排序后,中间那个格子向上下扩展,两边的格子再向中间连即可。
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long ll;
int mx,mi,ans;
pair<int,int> a[4];
int read()
{
int ret=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return f?ret:-ret;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
#endif
mx=0;mi=1000;
for(int i=1;i<=3;++i)
{
a[i].fi=read(),a[i].se=read();
mx=max(mx,a[i].se);mi=min(mi,a[i].se);
}
sort(a+1,a+4);
ans+=mx-mi+1;
ans+=a[2].fi-a[1].fi;ans+=a[3].fi-a[2].fi;
printf("%d\n",ans);
for(int i=mi;i<=mx;++i) printf("%d %d\n",a[2].fi,i);
for(int i=a[1].fi;i<a[2].fi;++i) printf("%d %d\n",i,a[1].se);
for(int i=a[2].fi+1;i<=a[3].fi;++i) printf("%d %d\n",i,a[3].se);
return 0;
}
B.Minimum Diameter Tree
边权在叶子的父边处贡献一定优于其他边,因此将边权平均分配给每个叶子的父边即可。设叶子数为 ,则答案就是 。
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e5+10;
int n,S,cnt,siz[N];
int read()
{
int ret=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return f?ret:-ret;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("B.in","r",stdin);
freopen("B.out","w",stdout);
#endif
n=read();S=read();
for(int i=1;i<n;++i)
{
int u=read(),v=read();
++siz[u];++siz[v];
}
for(int i=1;i<=n;++i) if(siz[i]==1) ++cnt;
printf("%.12lf\n",(db)S/(db)cnt*2);
return 0;
}
C.Vasya and Templates
考虑 和 第一个不同的位置,那么在这之前 的置换一定是唯一确定的。在这之后,我们可以考虑 是贴着上边界还是贴着下边界,或可以不贴着边界(即直接满足答案)。然后分情况讨论即可,细节比较多。
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long ll;
const int N=1e6+10,M=28;
int n,flag,ff,cnt;
int a[N],b[N],c[N];
int tg[M],cg[M],bo[M];
bool used[M],use[M];
char A[N],B[N],C[N];
int read()
{
int ret=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return f?ret:-ret;
}
void clear()
{
flag=1;cnt=0;
memset(used,0,sizeof(used));memset(use,0,sizeof(use));memset(tg,0,sizeof(tg));
memset(bo,0,sizeof(bo));memset(cg,0,sizeof(cg));
}
void output()
{
puts("YES");
int j=1;
for(int i=1;i<=cnt;++i)
{
if(tg[i]) cg[i]=tg[i];
if(!cg[i])
{
while(used[j] || use[j]) ++j;
cg[i]=j;use[j]=1;
}
putchar(cg[i]+'a'-1);
}
puts("");
}
void checkup(int p)
{
for(int i=p+1;i<n;++i)
{
if(tg[c[i]])
{
if(tg[c[i]]>a[i]) return;
if(tg[c[i]]==a[i]) continue;
ff=0;break;
}
else
{
for(int j=a[i]+1;j<=cnt;++j)
if(!use[j]) {tg[c[i]]=j;use[j]=1;return;}
if(!use[a[i]]) {tg[c[i]]=a[i];use[a[i]]=1;continue;}
ff=0;break;
}
}
}
void checkdown(int p)
{
for(int i=p+1;i<n;++i)
{
if(tg[c[i]])
{
if(tg[c[i]]<b[i]) return;
if(tg[c[i]]==b[i]) continue;
ff=0;break;
}
else
{
for(int j=1;j<b[i];++j)
if(!use[j]) {tg[c[i]]=j;use[j]=1;return;}
if(!use[b[i]]) {tg[c[i]]=b[i];use[b[i]]=1;continue;}
ff=0;break;
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
#endif
int T=read();
while(T--)
{
clear();cnt=read();
scanf("%s%s%s",C,A,B);n=strlen(C);
if(strcmp(A,B)>0) {puts("NO");continue;}
for(int i=0;i<n;++i)
{
a[i]=A[i]-'a'+1,b[i]=B[i]-'a'+1,c[i]=C[i]-'a'+1;
//cnt=max(cnt,a[i]);cnt=max(cnt,b[i]);cnt=max(cnt,c[i]);
}
int i;
for(i=0;i<n;++i)
{
if(a[i]!=b[i]) break;
if(cg[c[i]])
{
if(cg[c[i]]==a[i]) continue;
else {flag=0;break;}
}
else
{
if(used[a[i]]){flag=0;break;}
cg[c[i]]=a[i],used[a[i]]=1;
}
}
if(!flag) {puts("NO");continue;}
if(i>=n){output();continue;}
if(cg[c[i]])
{
if(cg[c[i]]>a[i] && cg[c[i]]<b[i]) {output();continue;}
if(cg[c[i]]<a[i] || cg[c[i]]>b[i]) {puts("NO");continue;}
ff=1;memcpy(tg,cg,sizeof(cg));memcpy(use,used,sizeof(used));
if(cg[c[i]]==a[i]) checkup(i);
else checkdown(i);
if(ff) {output();continue;}
}
else
{
for(int j=a[i]+1;j<b[i];++j) if(!used[j]) {cg[c[i]]=j;used[j]=1;break;}
if(cg[c[i]]>a[i] && cg[c[i]]<b[i]) {output();continue;}
if(!used[a[i]])
{
memcpy(tg,cg,sizeof(cg));memcpy(use,used,sizeof(used));
ff=1;tg[c[i]]=a[i];use[a[i]]=1;
checkup(i);
if(ff) {output();continue;}
}
if(!used[b[i]])
{
memcpy(tg,cg,sizeof(cg));memcpy(use,used,sizeof(used));
ff=1;tg[c[i]]=b[i];use[b[i]]=1;
checkdown(i);
if(ff) {output();continue;}
}
}
puts("NO");
}
return 0;
}
D.Rock-Paper-Scissors Champion
考虑一个人能成为胜者的充要条件,则为他的左右两边都有能被它(严格)打败的人或没有能赢他的人。因为我们用 维护出每个东西的第一个和最后一个人并用 维护一个前缀人数就可以计算答案了。
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long ll;
const int N=2e5+10,M=3;
int n,Q,ans;
char s[N];
set<int>st[M];
int read()
{
int ret=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return f?ret:-ret;
}
struct BIT
{
#define lowbit(x) (x&(-x))
int c[N];
void update(int x,int v){for(;x<N;x+=lowbit(x))c[x]+=v;}
int query(int x){int res=0;for(;x;x-=lowbit(x))res+=c[x];return res;}
}bit[M];
int id(char c){if(c=='R')return 0;else if(c=='S')return 1;return 2;}
int calc(int p)
{
int win=(p+1)%M,lose=(p-1+M)%M;
if(st[p].empty()) return bit[win].query(n);
if(st[lose].empty()) return 0;
return bit[win].query(n)-bit[win].query(max(*st[p].rbegin(),*st[lose].rbegin()))+
bit[win].query(*st[lose].rbegin())-bit[win].query(*st[lose].begin())+
bit[win].query(min(*st[p].begin(),*st[lose].begin()));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("D.in","r",stdin);
freopen("D.out","w",stdout);
#endif
n=read();Q=read();scanf("%s",s+1);
for(int i=1;i<=n;++i)
{
int p=id(s[i]);
bit[p].update(i,1);st[p].insert(i);
}
ans=calc(0)+calc(1)+calc(2);
printf("%d\n",ans);
while(Q--)
{
int p=read();char ch;scanf("%c",&ch);
if(s[p]==ch){printf("%d\n",ans);continue;}
int las=id(s[p]),now=id(ch);s[p]=ch;
bit[las].update(p,-1);bit[now].update(p,1);
st[las].erase(p);st[now].insert(p);
ans=calc(0)+calc(1)+calc(2);
printf("%d\n",ans);
}
return 0;
}
E.Beautiful Matrix
考虑枚举哪一位的字典序给定矩阵来计算答案,那么我们实际上要处理的就是一个类似错排的问题。现在考虑第 行第 列的字典序小于给定矩阵,那么这一位放置的数字有两种情况:用了第 行第 列及以后的数字或没有用,分开进行贡献即可。
还要处理的一个问题是如何计算 个数字的错排但其中的 个可以任意放置的方案数。设这个东西为 ,那么我们有 ,特别地,
#include<bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long ll;
const int N=2005,mod=998244353;
int n,a[N][N];
ll ans,fac[N],f[N][N];
int read()
{
int ret=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return f?ret:-ret;
}
struct BIT
{
#define lowbit(x) (x&(-x))
ll c[N];
void clear(){memset(c,0,sizeof(c));}
void update(int x,ll v){for(;x<N;x+=lowbit(x))c[x]+=v;}
void upzero(int x){ll t=Query(x,x);update(x,-t);}
ll query(int x){ll res=0;for(;x;x-=lowbit(x))res+=c[x];return res;}
ll Query(int l,int r){return query(r)-query(l-1);}
}bit1,bit2;
ll upm(ll x){return x<0?x+mod:x;}
void up(ll &x,ll y){x+=y;if(x>=mod)x-=mod;}
int main()
{
#ifndef ONLINE_JUDGE
freopen("E.in","r",stdin);
freopen("E.out","w",stdout);
#endif
n=read();
fac[0]=1;for(int i=1;i<=n;++i)fac[i]=fac[i-1]*i%mod;
for(int i=0;i<=n;++i)
{
f[i][0]=fac[i];
for(int j=1;j<=i;++j) f[i][j]=upm(f[i][j-1]-f[i-1][j-1]);
}
for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) a[i][j]=read();
for(int i=1;i<=n;++i) bit1.update(i,1);
for(int i=1;i<=n;++i)
{
up(ans,bit1.query(a[1][i]-1)*fac[n-i]%mod);
bit1.update(a[1][i],-1);
}
for(int i=2;i<=n;++i)
{
ans=ans*f[n][n]%mod;
bit1.clear();bit2.clear();
for(int j=1;j<=n;++j) bit1.update(j,1),bit2.update(j,1);
for(int j=1;j<=n;++j)
{
bit2.upzero(a[i-1][j]);
int s1=bit1.query(a[i][j]-1),s2=bit2.query(a[i][j]-1);
int s3=bit2.query(n);
if(a[i][j]>a[i-1][j] && bit1.Query(a[i-1][j],a[i-1][j])) --s1;
up(ans,(s1-s2+mod)*f[n-j][s3]%mod);
if(s3>0) up(ans,s2*f[n-j][s3-1]%mod);
bit1.update(a[i][j],-1);bit2.upzero(a[i][j]);
}
}
printf("%lld\n",upm(ans%mod));
return 0;
}
F.Forest Fires
不会做,我们直接贴上zzq的代码。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <bitset>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <sstream>
#include <stack>
#include <iomanip>
using namespace std;
#define pb push_back
#define mp make_pair
typedef pair<int,int> pii;
typedef long long ll;
typedef double ld;
typedef vector<int> vi;
#define fi first
#define se second
#define fe first
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
#define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
#define es(x,e) (int e=fst[x];e;e=nxt[e])
#define esb(x,e,b) (int e=fst[x],b=vb[e];e;e=nxt[e],b=vb[e])
#define SZ 666666
#define yn yyn
int n,t,x[SZ],y[SZ];
int ys[SZ],yn;
pair<int,pair<pii,int> > os[SZ]; int on;
const int M=128;
pii operator + (pii a,pii b)
{
if(a.fi<b.fi) return a;
if(b.fi<a.fi) return b;
return pii(a.fi,a.se+b.se);
}
pii seg[SZ]; int tg[SZ],ls[SZ],rs[SZ];
void pd(int x)
{
if(!tg[x]) return;
seg[x].fi+=tg[x];
if(x<=M)
tg[x+x]+=tg[x],tg[x+x+1]+=tg[x];
tg[x]=0;
}
void upd(int x)
{
pd(x+x); pd(x+x+1);
seg[x]=seg[x+x]+seg[x+x+1];
}
void edt(int x,int l,int r,int v)
{
if(l>r||rs[x]<l||r<ls[x]) return;
pd(x);
if(l<=ls[x]&&rs[x]<=r)
{
tg[x]+=v; return;
}
edt(x+x,l,r,v);
edt(x+x+1,l,r,v);
upd(x);
}
map<int,ll> rss;
ll calc(int s)
{
if(rss.count(s)) return rss[s];
yn=0;
for(int i=1;i<=n;++i)
ys[++yn]=y[i]-s,ys[++yn]=y[i]+s+1;
sort(ys+1,ys+1+yn); yn=unique(ys+1,ys+1+yn)-ys-1;
int tot=ys[yn]-ys[1]; on=0;
for(int i=1;i<=n;++i)
{
int L=lower_bound(ys+1,ys+1+yn,y[i]-s)-ys,
R=lower_bound(ys+1,ys+1+yn,y[i]+s+1)-ys;
os[++on]=mp(x[i]-s,mp(pii(L,R-1),1));
os[++on]=mp(x[i]+s+1,mp(pii(L,R-1),-1));
}
sort(os+1,os+1+on);
for(int i=1;i<=M+M;++i) seg[i]=pii(0,0),tg[i]=0;
for(int i=1;i<yn;++i) seg[i+M]=pii(0,ys[i+1]-ys[i]);
for(int i=M-1;i>=1;--i) seg[i]=seg[i+i]+seg[i+i+1];
ll ans=0;
for(int i=1;i<=on;++i)
edt(1,os[i].se.fi.fi,os[i].se.fi.se,os[i].se.se),
ans+=(tot-seg[1].se)*ll(os[i+1].fi-os[i].fi);
return rss[s]=ans;
}
ll cd(int s)
{
return calc(s)-calc(s-1);
}
const int MOD=998244353;
ll S1(ll x)
{return x*(x+1)/2%MOD;}
ll S2(ll x)
{
ll t[]={x,x+1,2*x+1};
for(int i=0;i<3;++i)
if(t[i]%2==0) {t[i]/=2; break;}
for(int i=0;i<3;++i)
if(t[i]%3==0) {t[i]/=3; break;}
return t[0]*(ll)t[1]%MOD*t[2]%MOD;
}
bool cp(ll l,ll r)
{
if(l>=r) return 1;
return cd(r)-cd(l)==(r-l)*(cd(l+1)-cd(l));
}
int main()
{
for(int i=1;i<=M;++i) ls[i+M]=rs[i+M]=i;
for(int i=M-1;i>=1;--i) ls[i]=ls[i+i],rs[i]=rs[i+i+1];
// n=50,t=1e6;
cin>>n>>t;
for(int i=1;i<=n;++i)
// x[i]=rand()*32+rand(),y[i]=rand()*32+rand();
cin>>x[i]>>y[i];
// ll aa=0;
// for(int i=1;i<=t;++i) aa+=cd(i)*i,aa%=MOD;
// cout<<aa<<"\n";
// return 0;
ll L=1,ans=0;
while(L<=t)
{
if(L==t)
{
ans+=cd(L)%MOD*L;
ans%=MOD;
break;
}
ll u=cd(L+1)-cd(L);
ll l=L+1,r=t;
while(l<r)
{
ll m=(l+r+1)>>1;
if(cd(m)-cd(m-1)!=u
||(!cp(L,m))||(!cp(L,m-1))
||(!cp(L,m-2))||(!cp(L,m-3)))
r=m-1;
else l=m;
}
ll b=cd(L),n=l-L;
b%=MOD; u%=MOD;
//(b+u*i)*(i+L) i in [0,n]
ans+=S2(n)*u+S1(n)*((u*L+b)%MOD)+L*b%MOD*(n+1);
ans%=MOD;
L=l+1;
}
ans=(ans%MOD+MOD)%MOD;
cout<<ans<<"\n";
}