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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Codeforces Round #665 (Div. 2)

發布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Codeforces Round #665 (Div. 2) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2020/8/21 晚上打完球就22:10了,愣是沒報上名(cf打不開,然后就做了一下賽后交的過了3個題

A - Distance and Axis

數學題分類討論一下即可

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<iostream> #include<algorithm> using namespace std; int n,k; int main() {IO;int T;cin>>T;while(T--){cin>>n>>k;int res=0;if(k>n){res+=k-n;}else{if(k%2!=n%2) res++;}cout<<res<<endl;}return 0; }

B - Ternary Sequence

貪心,先讓第一個序列的2找第二個序列的1配對(加分), 然后看看第一個序列的1先找第二個序列的0和1配對(分數不變),最后找第二個序列2配對(減分)

#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; ll x,y,z; ll a,b,c; int main() {IO;int T;cin>>T;while(T--){cin>>x>>y>>z;cin>>a>>b>>c;ll res=0;res+=2*min(z,b);y-=a;y-=b-min(z,b);if(y>0) res-=2*y;cout<<res<<endl;}return 0; }

C - Mere Array

這題是個腦筋急轉彎。首先先找到數組中最小的數mina如果想要交換兩個數,那么兩個數的最大公因數必須是mina,然后可以先把原數組排序不妨記作數組b[],如果a[i]!=b[i]說明原數組中該位置的值需要交換位置,那么這個數必須是mina的倍數,并且只要是這個數的倍數就一定能交換(我們可以考慮讓它和mina所在位置交換)。因此只要位置不正確的數全都是mina的倍數就可以滿足題意。

#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=200010; int a[N],b[N]; int n; int main() {IO;int T;cin>>T;while(T--){cin>>n;int mina=1e9+1;for(int i=1;i<=n;i++) {cin>>a[i];b[i]=a[i];mina=min(mina,a[i]);}sort(b+1,b+1+n);bool ok=1;for(int i=1;i<=n;i++)if(a[i]!=b[i]&&a[i]%mina!=0) {ok=0;break;}if(ok) cout<<"YES"<<endl;else cout<<"NO"<<endl;}return 0; }

D - Maximum Distributed Tree

貪心:可以考慮統計每條邊通過的次數,然后通過次數多的分配邊權最大。
如何統計每條邊通過次數?
考慮樹中的一條邊,如果將該邊去掉將會分成兩部分,可以統計該兩部分的點的數量,該邊的通過次數即兩部分相乘一部分點數為sz那么另一部分即為n-sz那么該邊通過次數即sz*(n-sz)。跑一個dfs即可統計出來。
目前有n-1條邊待分配邊權,有m個邊權值,如果m>n-1,把前幾個大數乘起來(保證所有邊權乘起來等于k)分配給經過邊數最多的那條邊。如果m==n-1那么就一個邊一個數貪心經過次數多的邊權重大。如果m<n-1最后幾條邊權重是1。
(之前沒考慮m>n-1這種情況wwwsTO)

#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; typedef long long ll; typedef pair<int,int> pii; const int mod=1e9+7; const int N=100010,M=2*N; int n,m; int h[N],e[M],ne[M],idx; vector<ll>w; ll sz[N],p[N]; void add(int a,int b) {e[idx]=b;ne[idx]=h[a];h[a]=idx++; } void dfs(int u,int fa) {sz[u]=1;for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];if(j==fa) continue;dfs(j,u);sz[u]+=sz[j];w.push_back(1ll*sz[j]*(n-sz[j]));} } void init(int n) {for(int i=0;i<=n;i++) h[i]=-1;w.clear();idx=0; } int main() {IO;int T;cin>>T;while(T--){cin>>n;init(n);for(int i=1;i<n;i++){int a,b;cin>>a>>b;add(a,b);add(b,a);}cin>>m;for(int i=0;i<m;i++) cin>>p[i];sort(p,p+m);reverse(p,p+m);dfs(1,-1);sort(w.begin(),w.end());reverse(w.begin(),w.end());ll res=0;if(m<=w.size()){for(int i=0;i<m;i++) res=(res+1ll*(w[i]%mod*p[i]%mod))%mod;for(int i=m;i<w.size();i++) res=(res+w[i])%mod;}else{int k=m-w.size();res=w[0]%mod;for(int i=0;i<=k;i++) res=res*p[i]%mod;for(int i=k+1;i<m;i++) res=(res+w[i-k]%mod*p[i]%mod)%mod;}cout<<res<<endl;}return 0; }

F-Reverse and Swap

F題Reverse and Swap
留個坑,回來補這題數據結構
2020/8/23補
方法一:
首先這題單點修改,區間查詢無疑線段樹可以做。
考慮如何進行區間交換?
由于數組線段樹固定做兒子和右兒子的下標父節點 u 左孩子u<<1 右孩子u<<1|1,傳統方式不宜進行區間交換,因此采用指針方式記錄左右孩子(主席樹方式)那么區間交換直接交換左右孩子即可,而區間反轉則是遞歸交換左右子樹直到葉子節點。
嘗試用懶標極維護區間操作:lazy看成一個二進制數(狀態壓縮),對于一個節點如果lazy^id!=0說明id中的1所在的位置lazy中也是1那么表示需要該節點的左右子樹。
于是區間反轉則是在根節點直接打上標記tree[root].lazy^=(1<<(k+1))-1;
區間交換則tree[root].lazy^=1<<(k+1);
參考大佬題解

// [1 2 3 4 5 6 7 8] 1000 id:3 // [1 2 3 4] [5 6 7 8] 0100 id:2 // [1 2] [3 4] [5 6] [7 8] 0010 id:1 // [1][2][3][4][5][6][7][8] 0001 id:0 #define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<vector> #include<set> #include<map> #include<string> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N=(1<<18)+10; int n,q; ll a[N]; struct node {int l,r;ll s;int id,lazy; }tree[40*N]; int cnt,root; void pushup(int u) {tree[u].s=tree[tree[u].l].s+tree[tree[u].r].s; } void pushdown(int u) {if(tree[u].id&tree[u].lazy){swap(tree[u].l,tree[u].r);tree[u].lazy^=tree[u].id;}tree[tree[u].l].lazy^=tree[u].lazy;tree[tree[u].r].lazy^=tree[u].lazy;tree[u].lazy=0;} void build(int &u,int l,int r) {u=++cnt;tree[u].id=r-l+1;tree[u].lazy=0;if(l==r){tree[u].s=a[l];return;}int mid=l+r>>1;build(tree[u].l,l,mid);build(tree[u].r,mid+1,r);pushup(u); } void modify(int u,int l,int r,int pos,int x) {if(l==r){tree[u].s=x;return;}pushdown(u);int mid=l+r>>1;if(pos<=mid) modify(tree[u].l,l,mid,pos,x);else modify(tree[u].r,mid+1,r,pos,x);pushup(u); } ll query(int u,int l,int r,int vl,int vr) {if(vl<=l&&r<=vr) return tree[u].s;pushdown(u);int mid=l+r>>1;ll v=0;if(vl<=mid) v+=query(tree[u].l,l,mid,vl,vr);if(vr>mid) v+=query(tree[u].r,mid+1,r,vl,vr);pushup(u);return v; } void rev(int k) {tree[root].lazy^=(1<<(k+1))-1;if(tree[root].id&tree[root].lazy){swap(tree[root].l,tree[root].r);tree[root].lazy^=tree[root].id;} } void swp(int k) {tree[root].lazy^=1<<(k+1);if(tree[root].id&tree[root].lazy){swap(tree[root].l,tree[root].r);tree[root].lazy^=tree[root].id;} } int main() {IO;cin>>n>>q;for(int i=1;i<=1<<n;i++) cin>>a[i];build(root,1,1<<n);while(q--){int op,x,y;cin>>op;if(op==1){cin>>x>>y;modify(root,1,1<<n,x,y);}else if(op==2){cin>>x;rev(x);}else if(op==3){cin>>x;swp(x);}else {cin>>x>>y;cout<<query(root,1,1<<n,x,y)<<endl;}}return 0; }

看standing發現了一個神奇的做法自己寫一下
方法二:
把線段樹看成一層一層的,可以發現反轉和交換操作都是在同層進行,因此可以以層數記錄lazy,方法一是用swap操作實現reverse操作,同樣其實也可以用reverse操作實現swap:可以先把上一層每個區間進行reverse然后把該層的每個區間再reverse實際上實現的就是swap操作。
之前說過傳統線段樹不宜進行區間反轉等操作,這個方法秒在不進行區間反轉操作,只記錄每層的區間是否需要進行反轉,僅僅在查詢和更改時候進行相應的坐標變化即可。

// [1 2 3 4 5 6 7 8] level:3 // [1 2 3 4] [5 6 7 8] level:2 // [1 2] [3 4] [5 6] [7 8] level:1 // [1][2][3][4][5][6][7][8] level:0 // 區間交換 level=2 只需要先反轉level=3 然后再反轉level=2即可 #define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<vector> #include<set> #include<map> #include<string> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N=(1<<18)+10; int n,q; int b[20]; ll a[N]; struct node {int l,r,level;ll val; }tree[4*N]; 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 level) {tree[u]={l,r,level};if(l==r){tree[u].val=a[l];return;}int mid=l+r>>1;build(u<<1,l,mid,level-1);build(u<<1|1,mid+1,r,level-1);pushup(u); } void modify(int u,int pos,int x) {if(tree[u].l==tree[u].r){tree[u].val=x;return;}if(b[tree[u].level]) pos=tree[u].r-(pos-tree[u].l);int mid=tree[u].l+tree[u].r>>1;if(pos<=mid) modify(u<<1,pos,x);else modify(u<<1|1,pos,x);pushup(u); } ll query(int u,int l,int r) {if(tree[u].l==l&&r==tree[u].r) return tree[u].val;int lnow=l,rnow=r;if(b[tree[u].level]){lnow=tree[u].r-(r-tree[u].l);rnow=tree[u].r-(l-tree[u].l);}ll v=0;int mid=tree[u].l+tree[u].r>>1;if(rnow<=mid) v+=query(u<<1,lnow,rnow);else if(lnow>mid) v+=query(u<<1|1,lnow,rnow);else{v+=query(u<<1,lnow,mid);v+=query(u<<1|1,mid+1,rnow);}return v; } int main() {cin>>n>>q;for(int i=1;i<=1<<n;i++) cin>>a[i];build(1,1,1<<n,n);while(q--){int op,x,y;cin>>op;if(op==1){cin>>x>>y;modify(1,x,y);}else if(op==2){cin>>x;b[x]^=1;}else if(op==3){cin>>x;b[x]^=1;b[x+1]^=1;}else {cin>>x>>y;cout<<query(1,x,y)<<endl;}}return 0; }

要加油哦~

總結

以上是生活随笔為你收集整理的Codeforces Round #665 (Div. 2)的全部內容,希望文章能夠幫你解決所遇到的問題。

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