cf1900+训练
B. Letter Exchange 1900
https://codeforces.com/problemset/problem/1784/B
题解:对于每个字符串,若一个人w>1,n=0则其必然需要在某一步操作种交出w得到n或交出w得到i,再交出i得到n,我们可以把这个交换抽象为一条边w->n,对于图中的一组长度为2的环,即x->y->x,可以用一次交换解决。直到图中无2环时,我们发现,每个点的入度和出度一致,故剩下的环都为w->i->n->w的3元环,而对于每个三元环,容易知道只需两次交换即可消除,即可得到答案。
代码:
#include<bits/stdc++.h>
using namespace std;
char ff[10];
int cnt[10],f[5][5];
stack<int> g[5][5];
struct node{
int x,y;
char c1,c2;
}res[100100];
void solve(){
int n;cin>>n;
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
f[i][j]=0;
while(g[i][j].size()) g[i][j].pop();
}
}
for(int k=1;k<=n;k++){
cnt[1]=cnt[2]=cnt[3]=0;
int p=-1,q=-1;
string s;cin>>s;
for(int i=0;i<3;i++){
int c=s[i];
if(c=='w') cnt[1]++;
else if(c=='i') cnt[2]++;
else if(c=='n') cnt[3]++;
}
for(int i=1;i<=3;i++){
if(cnt[i]==3){
for(int j=1;j<=3;j++){
if(j==i) continue;
f[i][j]++;
g[i][j].push(k);
}
break;
}
if(cnt[i]==2) p=i;
else if(cnt[i]==0) q=i;
}
if(p>0&&q>0) f[p][q]++,g[p][q].push(k);
}
int ans=0;
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
if(i==j) continue;
while(f[i][j]&&f[j][i]){
ans++;
int x=g[i][j].top();g[i][j].pop();
int y=g[j][i].top();g[j][i].pop();
f[i][j]--,f[j][i]--;
res[ans].x=x,res[ans].y=y,res[ans].c1=ff[i],res[ans].c2=ff[j];
}
int k=6-i-j;
while(f[i][j]&&f[j][k]){
ans++;
int x=g[i][j].top();g[i][j].pop();
int y=g[j][k].top();g[j][k].pop();
f[i][j]--,f[j][k]--;
f[i][k]++;
g[i][k].push(y);
res[ans].x=x,res[ans].y=y,res[ans].c1=ff[i],res[ans].c2=ff[j];
}
}
}
cout<<ans<<endl;
for(int i=1;i<=ans;i++){
cout<<res[i].x<<" "<<res[i].c1<<" "<<res[i].y<<" "<<res[i].c2<<endl;
}
}
signed main(){
ff[1]='w',ff[2]='i',ff[3]='n';
int T;cin>>T;
while(T--) solve();
}
Up the Strip 1900
https://www.luogu.com.cn/problem/CF1558B
题解:对于从n到1的点,我们考虑谁能到达它:所有比它大的位置,以及kx,kx+1,,,k*x+k-1(1<k<=x),即可完成转移。结合后缀和我们可以将复杂度优化为n(1+1/2+,,,+1/n)=nlogn,可通过本题。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int f[4000010],s[4000010];
signed main(){
int n,m;cin>>n>>m;
f[n]=1;
s[n]=1;
for(int i=n-1;i>=1;i--){
f[i]=(f[i]+s[i+1])%m;
for(int j=2;j*i<=n;j++){
int w=min(n+1,i*j+j);
f[i]=(f[i]+s[i*j]-s[w]+m)%m;
}
s[i]=(s[i+1]+f[i])%m;
}
cout<<f[1];
}
C. Music Festival 1900(?感觉更高)
https://codeforces.com/problemset/problem/1801/C
题解:显然我们需要将每一个专辑预处理成递增序列,然后按照最大值从小到达将专辑排序。定义f(i,j)为前i个专辑中选择若干,最大值为j时得到的最大满意度。这个dp是n2的,无法通过。考虑优化,由于其实每次我们转移都是转移到同一个最大值,即更新数量很少,而询问是询问前缀最大满意度,即动态区间查询,单点修改,可以使用线段树优化,每次枚举第i个专辑递增序列的各个值,对f(i,m[i]) 以max(1,a[i][j]-1)+cnt更新,最后答案即为max(1,maxx).复杂度为O(nlogn).需要注意的是每次需要离散化数据来初始化否则会t。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+100;
int a[N],m[N],id[N],nex[N],pre[N];
int f[N],q[N];
struct node{
int c,l,r,lz;
}t[N*4];
void build(int p,int l,int r){
t[p].l=l,t[p].r=r;
if(l==r){
t[p].c=0,t[p].lz=0;
return;
}
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
}
void pushdown(int p){
if(!t[p].lz) return;
int w=t[p].lz;
t[p*2].c=max(t[p*2].c,t[p].lz);
t[p*2+1].c=max(t[p*2+1].c,w);
t[p*2].lz=max(t[p*2].lz,w);
t[p*2+1].lz=max(t[p*2+1].lz,w);
t[p].lz=0;
}
void change(int p,int l,int r,int k){
if(t[p].l>=l&&t[p].r<=r){
t[p].lz=k;
t[p].c=k;
return;
}
pushdown(p);
int mid=(t[p].l+t[p].r)/2;
if(l<=mid) change(p*2,l,r,k);
if(r>mid) change(p*2+1,l,r,k);
t[p].c=max(t[p*2].c,t[p*2+1].c);
}
int ask(int p,int l,int r){
if(t[p].l>=l&&t[p].r<=r){
return t[p].c;
}
pushdown(p);
int res=0,mid=(t[p].l+t[p].r)/2;
if(mid>=l) res=max(res,ask(p*2,l,r));
if(mid<r) res=max(res,ask(p*2+1,l,r));
return res;
}
bool cmp(int x,int y){
return m[x]<m[y];
}
void solve(){
int n;cin>>n;
int tot=0;
// build(1,1,200000);
vector<int> g[n+1];
for(int i=1;i<=n;i++){
id[i]=i;
int k;cin>>k;
int maxx=0;
for(int j=1;j<=k;j++){
int x;cin>>x;
if(x>maxx){
maxx=x;
q[++tot]=x;
g[i].push_back(x);
}
}
m[i]=maxx;
}
sort(q+1,q+tot+1);
int tt=0;
for(int i=1;i<=tot;i++){
if(q[i]==q[i-1]) continue;
f[q[i]]=++tt;
}
for(int i=1;i<=n;i++) m[i]=f[m[i]];
for(int i=0;i<=tt*4;i++){
t[i].c=0,t[i].lz=0,t[i].l=0,t[i].r=0;
}
build(1,1,tt);
sort(id+1,id+n+1,cmp);
for(int i=1;i<=n;i++){
int cnt=g[id[i]].size();
int maxx=ask(1,m[id[i]],m[id[i]]);
for(auto j:g[id[i]]){
int it=f[j];
int y=ask(1,1,it-1);
y=y+cnt;
if(y>maxx)
change(1,m[id[i]],m[id[i]],y);
maxx=max(maxx,y);
cnt--;
}
}
int ans=ask(1,1,tt);
cout<<ans<<endl;
}
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--) solve();
}

浙公网安备 33010602011771号