日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

牛客练习赛 58——树链剖分

發(fā)布時間:2023/12/3 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 牛客练习赛 58——树链剖分 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

A - 牛能和寶石

簽到題

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<iostream> #include<algorithm> using namespace std; const int N=100010; int a[N],b[N]; int n; int main() {IO;int T=1;//cin>>T;while(T--){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=n;i++) cin>>b[i];sort(a+1,a+1+n);sort(b+1,b+1+n);int res=0;for(int i=1;i<=n;i++) res=max(res,a[i]+b[n-i+1]);cout<<res<<'\n';}return 0;}

B - 牛妹和01串

簽到題

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<iostream> #include<algorithm> using namespace std; const int N=100010; int a[N],b[N]; int n; int main() {IO;int T=1;//cin>>T;while(T--){string s;cin>>s;int res=0,cnt0=0,cnt1=0;for(auto t:s){if(t=='1') cnt1++;if(t=='0') cnt0++;if(cnt0&&cnt1){res++;cnt0=0;cnt1=0;}}cout<<res<<'\n';}return 0; }

C - 矩陣消除游戲

m,nm,nm,n很小考慮直接枚舉
行列都枚舉會TLE,考慮優(yōu)化:如果行確定那么選擇列可以貪心。

TLE代碼——枚舉行列
//lajiTLE代碼 #define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N=20; int a[N][N]; int n,m,k; vector<int> state[N]; int lowbit(int x) {return x&-x; } int calc(int x) {int res=0;while(x){x-=lowbit(x);res++;}return res; } ll solve(int r,int c) {ll res=0;for(int i=0;i<n;i++)for(int j=0;j<m;j++)if((r>>i&1)||(c>>j&1)) res+=a[i][j];return res; } int main() {IO;int T=1;//cin>>T;while(T--){cin>>n>>m>>k;for(int i=0;i<n;i++) for(int j=0;j<m;j++) cin>>a[i][j];k=min(k,min(n,m));for(int i=0;i<1<<min(n,m);i++) state[calc(i)].push_back(i);ll res=0;for(int r=0;r<=k;r++){int c=k-r;for(int i=0;i<state[r].size();i++){int nowr=state[r][i];for(int j=0;j<state[c].size();j++){int nowc=state[c][j];res=max(res,solve(nowr,nowc));}}}cout<<res<<'\n';}return 0;}
AC代碼——枚舉行貪心列
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N=20; int a[N][N]; int n,m,k; vector<int> state[N]; int lowbit(int x) {return x&-x; } int calc(int x) {int res=0;while(x){x-=lowbit(x);res++;}return res; } int b[N]; ll solve(int row,int cnt) {ll res=0;for(int j=0;j<m;j++){b[j]=0;for(int i=0;i<n;i++){if(row>>i&1) continue;b[j]+=a[i][j];}}sort(b,b+m);reverse(b,b+m);for(int i=0;i<n;i++)if(row>>i&1)for(int j=0;j<m;j++) res+=a[i][j];for(int i=0;i<cnt;i++)res+=b[i];return res; } int main() {IO;int T=1;//cin>>T;while(T--){cin>>n>>m>>k;for(int i=0;i<n;i++) for(int j=0;j<m;j++) cin>>a[i][j];k=min(k,min(n,m));for(int i=0;i<1<<min(n,m);i++) state[calc(i)].push_back(i);ll res=0;for(int r=0;r<=k;r++){int c=k-r;for(int i=0;i<state[r].size();i++){int nowr=state[r][i];res=max(res,solve(nowr,c));}}cout<<res<<'\n';}return 0;}

D - 迷宮

題解好像是dp做的,我dijkstra瞎搞出來了。
分析題目不難知道向上走和向左走沒什么用,于是只考慮向右走和向下走

向右走的代價為0(不需要堵路)。
如果能向右走,那么如果在該點向下走那么就要花費1代價(堵路),否則向下走的代價為0。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<queue> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N=1010; int g[N][N]; int n,m; int dist[N][N]; bool st[N][N]; char s[N][N]; struct node {int d,x,y;bool operator<(const node& o) const{return d>o.d;} }; void bfs() {memset(dist,0x3f,sizeof dist);memset(st,0,sizeof st);dist[1][1]=0;priority_queue<node> q;q.push({0,1,1});while(q.size()){int x=q.top().x,y=q.top().y;q.pop();if(st[x][y]) continue;st[x][y]=1;int a,b;int ok1=1,ok2=0;a=x,b=y+1;if(a<1||b<1||a>n||b>m||g[a][b]) ok1=0;else {if(dist[a][b]>dist[x][y]){dist[a][b]=dist[x][y];q.push({dist[a][b],a,b});}}a=x+1,b=y;if(a<1||b<1||a>n||b>m||g[a][b]) ok2=0;else {if(dist[a][b]>dist[x][y]+ok1){dist[a][b]=dist[x][y]+ok1;q.push({dist[a][b],a,b});}}} } int main() {IO;int T=1;//cin>>T;while(T--){cin>>n>>m;for(int i=1;i<=n;i++) cin>>s[i]+1;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)g[i][j]=s[i][j]-'0';bfs();if(dist[n][m]==0x3f3f3f3f) cout<<-1<<'\n';else cout<<dist[n][m]<<'\n';}return 0;}

E - 最大GCD

首先暴力把每個aia_iai?的約數(shù)搞出來,用一個vector存儲一下,d[i]d[i]d[i]表示存在約數(shù)是iiiaia_iai?所在的位置下標。詢問同樣先把所有約數(shù)搞出來,然后逆序去vector<int> d[]二分查找看看是否在所給區(qū)間內即可。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<vector> #include<iostream> #include<algorithm> using namespace std; const int N=100010; int n,m; vector<int> d[N]; int main() {//IO;int T=1;//cin>>T;while(T--){cin>>n>>m;for(int i=1;i<=n;i++){int a;cin>>a;for(int j=1;j<=a/j;j++){if(a%j) continue;d[j].push_back(i);if(j!=a/j) d[a/j].push_back(i);}}while(m--){int l,r,x;cin>>l>>r>>x;vector<int> dx;for(int i=1;i<=x/i;i++){if(x%i) continue;dx.push_back(i);if(i!=x/i) dx.push_back(x/i);}sort(dx.begin(),dx.end());reverse(dx.begin(),dx.end());for(auto t:dx){if(!d[t].size()) continue;int lnow=lower_bound(d[t].begin(),d[t].end(),l)-d[t].begin();if(lnow>=d[t].size()) continue;if(d[t][lnow]<=r) {cout<<t<<'\n';break;}}}}return 0;}

F - XOR TREE

分析一下不難發(fā)現(xiàn)每個點對答案的貢獻有以下規(guī)律:

  • 如果路徑點數(shù)是奇數(shù)個點,那么等效于所有偶數(shù)次序的點被記錄一次
  • 如果路徑點數(shù)是偶數(shù)個點,那么所有點都被計入一次

①路徑點數(shù)可以根據(jù)求樹上路徑距離間接求得
②對于一條路徑上的奇偶點,可以根據(jù)端點的奇偶性+深度的奇偶性來確定。

因此樹剖后根據(jù)dfs序建立兩棵線段樹分別維護深度是奇數(shù)和深度是偶數(shù)點的區(qū)間異或值。
查詢和修改的時候只需要分類討論以下即可。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=200010; //*************************************************************** int read() {int x=0;char c=getchar();while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar();return x; } //*************************************************************** int n,q; int w[N],a[N],b[N]; int h[N],e[2*N],ne[2*N],idx; void add(int a,int b) {e[idx]=b;ne[idx]=h[a];h[a]=idx++; } int fa[N],dep[N],sz[N],son[N]; void dfs1(int u,int p) {sz[u]=1; fa[u]=p,dep[u]=dep[p]+1;for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];if(j==p) continue;dfs1(j,u);sz[u]+=sz[j];if(sz[j]>sz[son[u]])son[u]=j;} } int timestamp,dfn[N],top[N]; void dfs2(int u,int t) {dfn[u]=++timestamp;top[u]=t;if(!son[u]) return;dfs2(son[u],t);for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];if(j==fa[u]||j==son[u]) continue;dfs2(j,j);} } int lca(int u,int v) {while(top[u]!=top[v]){if(dep[top[u]]<dep[top[v]]) swap(u,v);u=fa[top[u]];}return dep[u]<dep[v]?u:v; } int dist(int u,int v) {return dep[u]+dep[v]-2*dep[lca(u,v)]; } struct node1 {struct node2{int l,r;int val;}tree[N<<2];void pushup(int u){tree[u].val=tree[u<<1].val^tree[u<<1|1].val;}void build(int u,int l,int r,int w[]){tree[u]={l,r};if(l==r) {tree[u].val=w[l];return;}int mid=l+r>>1;build(u<<1,l,mid,w),build(u<<1|1,mid+1,r,w);pushup(u);}void modify(int u,int pos,int val){if(tree[u].l==tree[u].r){tree[u].val=val;return;}int mid=tree[u].l+tree[u].r>>1;if(pos<=mid) modify(u<<1,pos,val);else modify(u<<1|1,pos,val);pushup(u);}int query(int u,int l,int r){if(tree[u].l>=l&&tree[u].r<=r) return tree[u].val;int v=0;int mid=tree[u].l+tree[u].r>>1;if(l<=mid) v^=query(u<<1,l,r);if(r>mid) v^=query(u<<1|1,l,r);return v;}int cquery(int u,int v){int val=0;while(top[u]!=top[v]){if(dep[top[u]]<dep[top[v]]) swap(u,v);val^=query(1,dfn[top[u]],dfn[u]);u=fa[top[u]];}if(dep[u]>dep[v]) swap(u,v);val^=query(1,dfn[u],dfn[v]);return val;} }A,B; int main() {//IO;int T=1;//cin>>T;while(T--){n=read(),q=read();memset(h,-1,sizeof h);for(int i=1;i<=n;i++) w[i]=read();for(int i=1;i<n;i++){int u,v;u=read(),v=read();add(u,v),add(v,u);}dfs1(1,0);dfs2(1,1);for(int i=1;i<=n;i++){if(dep[i]&1) a[dfn[i]]=w[i];else b[dfn[i]]=w[i];}A.build(1,1,n,a);B.build(1,1,n,b);while(q--){int op,x,y;op=read(),x=read(),y=read();if(op==1){if(dep[x]&1) A.modify(1,dfn[x],y);else B.modify(1,dfn[x],y);}else{int d=dist(x,y);int res=0;if(d&1){res=A.cquery(x,y)^B.cquery(x,y);}else{if(dep[x]&1) res=B.cquery(x,y);else res=A.cquery(x,y);}cout<<res<<'\n';}}}return 0;}

要加油哦~

總結

以上是生活随笔為你收集整理的牛客练习赛 58——树链剖分的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。