ZJNU 2021-07-14 个人排位赛3 部分题解

news/2024/11/25 0:41:42/

完全不会数据结构就比较离谱

Another One


A - Roadblock

Problem Link

题意

FJ的农场由 N N N个点 M M M条边组成,边存在边权

它每次都会沿着最短路径从点 1 1 1走到点 N N N

现在FJ的牛想选择这张图中的任意一条边,使其边权翻倍

问选择某条边翻倍后,FJ需要多走的距离的最大值是多少(最短路的最大增量)

标签

Dijkstra

SPFA

思路

先在原图中跑一遍SPFA,求出此时的最短路长度 o r i g i n a l D i s t a n c e originalDistance originalDistance并且回溯得到这条路的每一条边

因为只有把最短路上的边翻倍,FJ才有可能走更长的路

所以枚举这条路上的每一条边,翻倍后尝试再跑一遍最短路(这里推荐用Dijkstra),求出此时的最短路长度 c u r r e n t D i s t a n c e currentDistance currentDistance

答案就是 c u r r e n t D i s t a n c e − o r i g i n a l D i s t a n c e currentDistance-originalDistance currentDistanceoriginalDistance的最大值

代码

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;int n,m;
vector<P> G[105];
int dis[105];
int pre[105];
vector<P> edge;int curu,curv;void spfa()
{queue<int> q;mst(dis,INF);dis[1]=0;q.push(1);while(!q.empty()){int u=q.front();q.pop();for(P pd:G[u]){int v=pd.first,w=pd.second;if(dis[v]>dis[u]+w){dis[v]=dis[u]+w;q.push(v);pre[v]=u;}}}int pos=n;while(pos!=1){edge.pb(P(pos,pre[pos]));pos=pre[pos];}
}void dijkstra()
{priority_queue<P> pq;mst(dis,INF);dis[1]=0;pq.push(P(0,1));while(!pq.empty()){P pp=pq.top();pq.pop();int u=pp.second;if(dis[u]!=-pp.first)continue;for(P pd:G[u]){int v=pd.first,w=pd.second;if(u==curu&&v==curv||u==curv&&v==curu)w<<=1;if(dis[u]+w<dis[v]){dis[v]=dis[u]+w;pq.push(P(-dis[v],v));}}}
}void solve()
{cin>>n>>m;rep(i,1,m){int a,b,c;cin>>a>>b>>c;G[a].pb(P(b,c));G[b].pb(P(a,c));}spfa();int curans=dis[n];int maxans=0;for(P p:edge){curu=p.first;curv=p.second;dijkstra();maxans=max(maxans,dis[n]);}cout<<maxans-curans<<'\n';
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);solve();return 0;
}



B - Grass Planting

Problem Link

题意

FJ有张 N N N个点 N − 1 N-1 N1条边的树图

初始时每条边的边权为 0 0 0

有两种操作:

P P P操作会把 u u u v v v的最短路径上的每条边边权 + 1 +1 +1

Q Q Q操作则会询问某条边的边权(保证询问的两个点是相邻的)

标签

Segment Tree

LCA

DFS Clock

思路

暂无,等想好了再改

或者建议直接问余总

代码

//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define all(a) (a).begin(),(a).end()
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const ll mod=998244353;
const int dx[8]={0,1,0,-1,1,1,-1,-1},dy[8]={1,0,-1,0,1,-1,1,-1};
mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count());
ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}int n;const int MAXN=100050,MAXF=18;vector<int> G[MAXN];
int depth[MAXN];
int father[MAXN][MAXF];
bool vis[MAXN];int lll[MAXN],rrr[MAXN],sz[MAXN];
int clk=0;void dfs(int pos,int fa)
{vis[pos]=true;depth[pos]=depth[fa]+1;father[pos][0]=fa;for(int i=1;i<MAXF;i++)father[pos][i]=father[father[pos][i-1]][i-1];int cnt=G[pos].size();lll[pos]=++clk;sz[pos]=1;for(int i=0;i<cnt;i++){if(!vis[G[pos][i]]){dfs(G[pos][i],pos);sz[pos]+=sz[G[pos][i]];}}rrr[pos]=lll[pos]+sz[pos]-1;
}int lca(int a,int b)
{while(depth[a]<depth[b]){for(int i=MAXF-1;i>=0;i--){if(depth[b]-(1<<i)>=depth[a])b=father[b][i];}}while(depth[a]>depth[b]){for(int i=MAXF-1;i>=0;i--){if(depth[a]-(1<<i)>=depth[b])a=father[a][i];}}if(a==b)return a;while(father[a][0]!=father[b][0]){for(int i=MAXF-1;i>=0;i--){if(father[a][i]!=father[b][i]){a=father[a][i];b=father[b][i];}}}return father[a][0];
}struct node
{int l,r;ll sum,lazy;
}tree[MAXN*4];void push_up(int id)
{tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;
}void push_down(int id)
{if(tree[id].lazy){int m=tree[id].r-tree[id].l+1;tree[id<<1].lazy+=tree[id].lazy;tree[id<<1|1].lazy+=tree[id].lazy;tree[id<<1].sum+=tree[id].lazy*(m-(m>>1));tree[id<<1|1].sum+=tree[id].lazy*(m>>1);tree[id].lazy=0;}
}void buildTree(int id,int l,int r)
{tree[id].l=l;tree[id].r=r;tree[id].lazy=0;if(l==r){tree[id].sum=0;return;}int mid=(l+r)>>1;buildTree(id<<1,l,mid);buildTree(id<<1|1,mid+1,r);push_up(id);
}void update(int id,int L,int R,ll val)
{if(L<=tree[id].l&&R>=tree[id].r){tree[id].sum+=val*(tree[id].r-tree[id].l+1);tree[id].lazy+=val;return;}push_down(id);int mid=(tree[id].r+tree[id].l)>>1;if(L<=mid)update(id<<1,L,R,val);if(R>mid)update(id<<1|1,L,R,val);push_up(id);
}ll query_sum(int id,int L,int R)
{if(L<=tree[id].l&&R>=tree[id].r)return tree[id].sum;push_down(id);int mid=(tree[id].r+tree[id].l)>>1;ll ans=0;if(L<=mid)ans+=query_sum(id<<1,L,R);if(R>mid)ans+=query_sum(id<<1|1,L,R);return ans;
}void solve()
{int q;cin>>n>>q;repp(i,1,n){int a,b;cin>>a>>b;G[a].pb(b);G[b].pb(a);}dfs(1,0);buildTree(1,1,n);while(q--){string op;cin>>op;if(op=="P"){int u,v;cin>>u>>v;int z=lca(u,v);update(1,lll[u],lll[u],1);update(1,lll[v],lll[v],1);update(1,lll[z],lll[z],-2);}else{int u,v;cin>>u>>v;if(depth[u]<depth[v])swap(u,v);cout<<query_sum(1,lll[u],rrr[u])<<'\n';}}
}
int main()
{closeSync;//multiCase{solve();}return 0;
}



C - Hay Bales

Problem Link

标签

Implementation

代码

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;int a[10010];void solve()
{int n,s=0;cin>>n;rep(i,1,n){cin>>a[i];s+=a[i];}s/=n;int r=0;rep(i,1,n)r+=max(a[i]-s,0);cout<<r<<'\n';
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);solve();return 0;
}



D - Cow Photography II

Problem Link

E - Cow Photography I

Problem Link

题意

两道题大致意思相同,直接讲Hard版本

FJ会按某一种顺序让 N N N头牛排成一队照相

但每次在照相前,总会有一些牛会走出队列,然后随意插入队列中的某些位置

FJ就这样拍了 5 5 5张照,每次拍照后都会再让所有牛按原先安排的顺序排回去

现在只知道,对于每一头牛,在这 5 5 5张照片中它只会主动走到其他位置一次,剩余四张在拍照时不会主动移动(也可能 5 5 5张照片中都不走动)

试根据这 5 5 5张照片判断出原先安排的顺序是什么

标签

Sorting

(Hard Version) Hashing

思路

首先抓住题目的要点,也就是 5 5 5张照片中每头牛最多主动走到其他位置一次

也就是说,对于任意的两头牛 a , b a,b a,b,一开始 a a a排在 b b b前面

某一次照相中 a a a主动走到 b b b后面

另一次照相中 b b b主动走到 a a a前面

这两次照相 a , b a,b a,b的顺序和原先是不同的

但是其他三次照相都是按照原先顺序不会改变

所以可以通过牛的 i d id id反标记其原来的位置,可以利用Hash方法(map/unordered_map/gp_hash_table等)来记录

  • 利用 p o s [ i ] [ j ] pos[i][j] pos[i][j]表示在第 i i i次照相中,id为 j j j的牛的位置

那么在确定最终的顺序时,如果想要判断任意两头牛 a , b a,b a,b的顺序是怎样的,只需要检查在 5 5 5次照相中, a a a排在 b b b前面的次数多还是反之

但是由于 N = 20000 N=20000 N=20000,无法根据拓扑排序建图来获得答案

但可以根据快速排序 O ( n log ⁡ n ) O(n\log n) O(nlogn)的时间复杂度,重写id的判定规则来实现

总时间复杂度为 O ( n log ⁡ n log ⁡ n ) O(n\log n\log n) O(nlognlogn),使用unordered_map或gp_hash_table时可以优化成常数较大的 O ( n log ⁡ n ) O(n\log n) O(nlogn)

代码

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;int n;
int a[5][20010];
unordered_map<int,int> pos[5];struct node
{int id;bool operator < (const node& a) const{int l=0,r=0;repp(t,0,5){if(pos[t][id]<pos[t][a.id])l++;elser++;}return l>r;}
}ar[20010];void solve()
{cin>>n;repp(t,0,5){rep(i,1,n){cin>>a[t][i];pos[t][a[t][i]]=i; //id反记录位置}}rep(i,1,n)ar[i].id=a[0][i];sort(ar+1,ar+n+1);rep(i,1,n)cout<<ar[i].id<<'\n';
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);solve();return 0;
}



F - Simplifying the Farm

Problem Link

题意

N N N个点 M M M条边的图

要求求出最小生成树的路径权值和,以及不同的最小生成树的种类数

已知同样长度的边最多不超过 3 3 3

标签

Minimum Spanning Tree : Kruskal

Counting & Implementation

思路

(是最暴力的分类讨论实现)

最小生成树计数的矩阵数原理不适用于本题中这样的大数据

但题目给出了一条关键限制——同样长度的边最多不超过 3 3 3

并且数据范围中每条边的长度限制在 1 0 6 10^6 106以内

所以可以开一个 1 0 6 10^6 106大小的 vector<int> eg[i] 来记录长度为 i i i的边有哪些

根据最小生成树的 K r u s k a l Kruskal Kruskal算法,将边按照从小到大排序后,如果某条边两端的点处于不同的集合内,就将其加入最小生成树中,贡献是将图中独立的集合 − 1 -1 1

可以从 1 1 1 1 0 6 10^6 106枚举长度,忽略两端点已经在同一个集合内的边,将剩余的边取出进行分类讨论


如果相同长度的可取的边有且仅有一条,那么这条边必取

合并这条边的两端点集合

最小生成树总长度 + i +i +i i i i即当前枚举到的边的长度)

总种类数不变


如果相同长度的可取的边有两条

画图,得以下三种情况(图中每个小圆圈代表独立的集合)

picF-1

对于第一种情况(左一),两条边任意取一条即可

此时最小生成树总长度 + i +i +i即可

种类数也就是 C 2 1 = 2 C_2^1=2 C21=2,让总种类数乘上 2 2 2

对于其余情况(左二、左三),在Kruskal算法中每条边都是需要取的,都会使得图中的独立集合数 − 1 -1 1

此时最小生成树总长度 + 2 i +2i +2i

总种类数不变


如果相同长度的可取的边有三条

画图,得以下八种情况(蓝色数字表示涉及到的集合数量)

picF-2

按涉及到的集合数量进行讨论:

  • 集合数量为 2 2 2,仅一种情况(上一),此时三条边任选其一即可
    • 总长度加 i i i
    • 种类数乘 C 3 1 = 3 C_3^1=3 C31=3
  • 集合数量为 3 3 3,有两种情况(上二、下四)
    • 对于上二,重复的两条边任选其一,第三条边必选
      • 总长度加 2 i 2i 2i
      • 种类数乘 C 2 1 = 2 C_2^1=2 C21=2
    • 对于下四,三条边任选两条便可保证图联通
      • 总长度加 2 i 2i 2i
      • 种类数乘 C 3 2 = 3 C_3^2=3 C32=3
  • 集合数量为 4 4 4,有三种情况(上三、下一、下二)
    • 对于上三,重复的两条边任选其一,第三条边必选
      • 总长度加 2 i 2i 2i
      • 种类数乘 C 2 1 = 2 C_2^1=2 C21=2
    • 对于下一和下二,所有边都是必选边
      • 总长度加 3 i 3i 3i
      • 种类数不变
  • 集合数量为 5 5 5或者 6 6 6时,所有边都是必选的
    • 总长度加 3 i 3i 3i
    • 种类数不变

最后,根据上述各图的特性,综合 v e c t o r / s e t vector/set vector/set等容器来判断即可

代码

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;int n,m;
vector<P> eg[1000050];
int gp[40050];int fnd(int p)
{return p==gp[p]?p:(gp[p]=fnd(gp[p]));
}
void merge(int a,int b)
{gp[fnd(b)]=fnd(a);
}
void merge(P pd)
{merge(pd.first,pd.second);
}void kruskal()
{int tmp=1;ll mincost=0,kinds=1;rep(i,1,1000000){if(!eg[i].empty()){vector<P> vec;for(P &pd:eg[i]){int uu=fnd(pd.first),vv=fnd(pd.second);if(uu==vv)continue; //集合已经相同的话不纳入选择范围if(uu>vv)swap(uu,vv); //小在前大在后,方便判断vec.pb(P(uu,vv));}sort(vec.begin(),vec.end());if(vec.size()==1) //相同长度的(可选)边只有一条时{mincost+=i;merge(vec[0]);}else if(vec.size()==2) //相同长度的(可选)边有两条时{set<int> st; //涉及到的集合数量for(P pd:vec){st.insert(pd.first);st.insert(pd.second);}if(st.size()==2){mincost+=i;kinds=(kinds*2)%mod;merge(vec[0]);}else{mincost+=i*2;merge(vec[0]);merge(vec[1]);}}else if(vec.size()==3) //相同长度的(可选)边有三条时{set<int> st;for(P pd:vec){st.insert(pd.first);st.insert(pd.second);}if(st.size()==2){mincost+=i;kinds=(kinds*3)%mod;merge(vec[0]);}else if(st.size()==3){if(vec[0]==vec[1]||vec[1]==vec[2]) //存在两条边是相同的{if(vec[0]==vec[1]){mincost+=i*2;kinds=(kinds*2)%mod;merge(vec[0]);merge(vec[2]);}else{mincost+=i*2;kinds=(kinds*2)%mod;merge(vec[0]);merge(vec[1]);}}else{mincost+=i*2;kinds=(kinds*3)%mod;merge(vec[0]);merge(vec[1]);}}else if(st.size()==4){if(vec[0]==vec[1]||vec[1]==vec[2]){if(vec[0]==vec[1]){mincost+=i*2;kinds=(kinds*2)%mod;merge(vec[0]);merge(vec[2]);}else{mincost+=i*2;kinds=(kinds*2)%mod;merge(vec[0]);merge(vec[1]);}}else{mincost+=i*3;merge(vec[0]);merge(vec[1]);merge(vec[2]);}}else if(st.size()>=5){mincost+=i*3;merge(vec[0]);merge(vec[1]);merge(vec[2]);}}}}//mincost%=mod;cout<<mincost<<' '<<kinds<<'\n';
}void solve()
{cin>>n>>m;if(n==1){cout<<"0 1\n";return;}rep(i,1,m){int u,v,w;cin>>u>>v>>w;eg[w].pb(P(u,v));}rep(i,1,n)gp[i]=i;kruskal();
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);solve();return 0;
}



G - Umbrellas for Cows

Problem Link

题意

N N N头牛分散在某一长度为 M M M的数轴上的某些点

已知买一把宽度为 i i i的雨伞需要花费 C i C_i Ci

如果要将位置为 a , b a,b a,b的两头牛用一把雨伞盖住,则雨伞的宽度至少要为 b − a + 1 b-a+1 ba+1

问将所有牛盖住的最小花费是多少

在最优方案中,雨伞是允许重叠的

标签

Dynamic Programming

思路

明显的 O ( n 2 ) O(n^2) O(n2) D P DP DP

因为雨伞并不是说随着宽度 i i i增加, C i C_i Ci也一定会增加的,并且题目允许雨伞重叠

所以可以将宽度较小的雨伞与比其宽度大的雨伞中的最小花费取小,使得 C i C_i Ci最后呈一个递增的顺序

于是便可以进行 D P DP DP转移,转移方程为
d i s t a n c e = p [ i ] − p [ j + 1 ] + 1 d p [ i ] = m i n ( d p [ i ] , d p [ j ] + c [ d i s t a n c e ] ) , j < i distance=p[i]-p[j+1]+1\\ dp[i]=min(dp[i],dp[j]+c[distance]),\ j\lt i distance=p[i]p[j+1]+1dp[i]=min(dp[i],dp[j]+c[distance]), j<i

代码

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;int n,m;
int p[5050];
ll c[100050];
ll dp[5050];void solve()
{cin>>n>>m;rep(i,1,n)cin>>p[i];rep(i,1,m)cin>>c[i];sort(p+1,p+n+1);per(i,m-1,1)c[i]=min(c[i],c[i+1]);//rep(i,1,m) cerr<<"? "<<i<<' '<<c[i]<<'\n';dp[0]=0;rep(i,1,n){dp[i]=LINF;repp(j,0,i)dp[i]=min(dp[i],dp[j]+c[p[i]-p[j+1]+1]);}cout<<dp[n]<<'\n';
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);solve();return 0;
}



H - Routing Schemes

Problem Link

防AK 😦




I - SegmentTree!

Problem Link

标签

Segment Tree

代码

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;const int MAXN=1e5+50;ll a[MAXN];struct node
{int l,r;ll lazy,maxn;
}tree[MAXN<<2];void push_up(int id)
{tree[id].maxn=max(tree[id<<1].maxn,tree[id<<1|1].maxn);
}void push_down(int id)
{if(tree[id].lazy){int m=tree[id].r-tree[id].l+1;tree[id<<1].lazy+=tree[id].lazy;tree[id<<1|1].lazy+=tree[id].lazy;tree[id<<1].maxn+=tree[id].lazy;tree[id<<1|1].maxn+=tree[id].lazy;tree[id].lazy=0;}
}void buildTree(int id,int l,int r)
{tree[id].l=l;tree[id].r=r;tree[id].lazy=0;if(l==r){tree[id].maxn=a[l];return;}int mid=(l+r)>>1;buildTree(id<<1,l,mid);buildTree(id<<1|1,mid+1,r);push_up(id);
}void update(int id,int L,int R,ll val)
{if(L<=tree[id].l&&R>=tree[id].r){tree[id].maxn+=val;tree[id].lazy+=val;return;}push_down(id);int mid=(tree[id].r+tree[id].l)>>1;if(L<=mid)update(id<<1,L,R,val);if(R>mid)update(id<<1|1,L,R,val);push_up(id);
}ll query_max(int id,int L,int R)
{if(L<=tree[id].l&&R>=tree[id].r)return tree[id].maxn;push_down(id);int mid=(tree[id].r+tree[id].l)>>1;ll ans=-LINF;if(L<=mid)ans=max(ans,query_max(id<<1,L,R));if(R>mid)ans=max(ans,query_max(id<<1|1,L,R));return ans;
}int n,m;void solve()
{cin>>n>>m;rep(i,1,n)cin>>a[i];buildTree(1,1,n);while(m--){int op;cin>>op;if(op==1){int p; ll v;cin>>p>>v;update(1,p,p,v-a[p]);a[p]=v;}else{int l,r;cin>>l>>r;cout<<query_max(1,l,r)<<'\n';}}
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);solve();return 0;
}



J - Escaping the Farm

Problem Link

题意

N N N个数,要求选择一些数,使得按照十进制相加时不会产生进位

问最多能选择的数的数量

标签

Brute Force

思路

由于 N N N最大只有 20 20 20,直接 O ( 2 20 ) O(2^{20}) O(220)枚举出所有状态,模拟加法判断进位即可

代码

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;int n,a[22][11];bool check(int stat)
{rep(j,0,9){int t=0;rep(i,1,n){if(stat>>(i-1)&1)t+=a[i][j];}if(t>9)return false;}return true;
}void solve()
{cin>>n;rep(i,1,n){int d;cin>>d;int p=0;while(d){a[i][p]=d%10;d/=10;p++;}}int r=0;repp(t,1,1<<n){if(check(t))r=max(r,(int)__builtin_popcount(t));}cout<<r<<'\n';
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);solve();return 0;
}



K - Counting Graphs

Problem Link

防AK 😦




https://www.cnblogs.com/stelayuri/p/15012069.html


http://www.ppmy.cn/news/427490.html

相关文章

ZJNU 2021-07-16 个人排位赛5 部分题解

[广告位招租] 思路看不懂&#xff1f;代码来凑&#xff01;&#xff08;狗头保命&#xff09;代码里也放了注释了 Another One A - Minimizing Edges Link 题意 防AK&#xff0c;不读了 &#x1f626; B - No Time to Dry Link 题意 Bessie想涂一面墙&#xff0c;初始时…

SCAU2020春季个人排位赛div2 #3

这场没打 头文件见上一篇训练blog A题&#xff1a;hdu3183 题意&#xff1a;给你一个数字n&#xff0c;删除其中的m的数字&#xff0c;使得这个数字变得最小 题解&#xff1a;把最大的几个数字删除就好&#xff0c;最后注意前导0的去除&#xff0c;还有结果就是0的时候的保留…

集美大学第七届团体程序设计天梯赛第一场排位赛题解

目录 L1L1-1 I Say TingTing题目大意解题思路代码 L1-2魂环极限题目大意&#xff1a;解题思路代码实现 L1-3汉字序顺题目大意解题思路代码实现 L1-4晦气的原批题目大意解题思路代码实现 L1-5疑心病的老板题意解题思路代码 L1-6有色图题目大意出题报告解题思路代码 L1-7成绩排名…

GDUT_排位赛题解报告_第5场_C. 积木

题目&#xff1a; ChenJr已经两个月没有出门了&#xff0c;因此他已经无聊到开始用积木来玩搭房子游戏了。 ChenJr首先规定&#xff0c;对于搭建的每一栋房子&#xff0c;他只能选取长度为n的积木作为地基&#xff0c;之后他根据下述的规则进行搭建。 如果当前搭建的房子的最…

第十五届全国大学生智能汽车竞速比赛规则 (预览)

竞速比赛规则 第十五届竞赛规则导读 参加过往届比赛的队员可以通过下面内容了解第十五届规则主要变化。如果第一次参加比赛&#xff0c;则建议对于本文进行全文阅读。 竞速比赛共分为为四个组别。详细情况参加文档第一节中的介绍&#xff0c;比赛组别是按照比赛任务来进行划分…

2014新生暑假个人排位赛02 E. 木头人足球赛

E. 木头人足球赛 时间限制 1000 ms 内存限制 65536 KB 题目描述 木头人星的行动速度是地球上乌龟的 1/10 &#xff08;所以可以忽略移动的速度&#xff09;&#xff0c;可是他们也热爱运动&#xff0c;尤其是足球。 他们的足球规则跟人类的一样&#xff0c;足球场尺寸为标准 10…

团队程序设计天梯赛-1.21排位赛总结

文章目录 7-5 一帮一 (15 分)题目思路知识点代码 7-6 考试座位号 (15 分)题目思路代码 7-7 删除重复字符 (20 分)题目目标思路代码 7-8 最长的括号子串 (20 分)题目技巧代码 7-9 家庭房产 (25 分)题目知识点思路代码 7-10 直直直径 (25 分)题目知识点思路代码 7-11 储水问题 (2…

乒乓球单循环赛_乒乓球淘汰赛制和单循环赛制的比赛方法是什么?

展开全部 一、乒乓球淘汰赛制比赛方法: 1、32人先进行1轮淘汰赛,获胜的16人进入胜62616964757a686964616fe78988e69d8331333431363531者组,失败的16人进入败者组 2、败者组第一轮:16人参赛,失败的8人被淘汰,胜利者进入败者组第二轮(此时剩24人) 3、胜者组第一轮:16人参赛…