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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

2016 ACM/ICPC Asia Regional Shenyang Online

發(fā)布時間:2025/5/22 编程问答 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2016 ACM/ICPC Asia Regional Shenyang Online 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

I:QSC and Master

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5900

題意:

  給出n對數(shù)keyi,vali表示當前這對數(shù)的鍵值和權(quán)值,可以操作將連續(xù)的兩個數(shù)合并,如果滿足gcd(a[i],a[i+1])>1,得到的價值是兩個數(shù)的權(quán)值和,每次合并兩個數(shù)之后,這兩個數(shù)就會消失,然后旁邊的數(shù)會接上比如1 2 3 4 合并了 2 3 則 剩下1 4也可以合并

思路:區(qū)間dp

1:處理出任意區(qū)間內(nèi)的所有數(shù)是否可以合并

對于當前的[l,r]區(qū)間,如果區(qū)間[l+1,r-1]可以合并,且gcd(a[l]+a[r])!=1的話,則整個區(qū)間[l,r]可以合并,價值也就是前綴和

同理處理出其他的情況 ?[l,r-2] [l+1,r]

2:區(qū)間dp,對于當前的l,r區(qū)間,如果可以合并,則直接加上區(qū)間和

反之,則枚舉一個中間值k,找出區(qū)間內(nèi)最大滿足情況的值

#include<bits/stdc++.h> using namespace std; const int maxn=310; typedef long long ll; ll n; ll num[maxn],val[maxn]; ll dp[maxn][maxn]; ll out[maxn][maxn]; ll sum[maxn]; ll gcd(ll x,ll y){return x==0?y:gcd(y%x,x); } //確定1-n的最大值 void Dp(){memset(out,0,sizeof(out));for(ll l=2;l<=n;l++){for(ll i=1;i+l-1<=n;i++){ll j=i+l-1;if(dp[i][j]==1)out[i][j]=sum[j]-sum[i-1];else{for(ll k=i;k<j;k++){out[i][j]=max(out[i][j],out[i][k]+out[k+1][j]);}}}} } //判斷區(qū)間是否能合并 void query(){memset(dp,0,sizeof(dp));for(ll i=1;i<n;i++){if(gcd(num[i],num[i+1])!=1)dp[i][i+1]=1;}for(ll l=2;l<=n;l+=2){for(ll i=1;i+l-1<=n;i++){ll j=i+l-1;if(gcd(num[i],num[j])!=1&&dp[i+1][j-1]==1)dp[i][j]=1;if(gcd(num[i],num[i+1])!=1&&dp[i+2][j]==1)dp[i][j]=1;if(gcd(num[j-1],num[j])!=1&&dp[i][j-2]==1)dp[i][j]=1;}}Dp(); }int main(){ll t;scanf("%lld",&t);while(t--){scanf("%lld",&n);memset(sum,0,sizeof(sum));for(ll i=1;i<=n;i++){scanf("%lld",&num[i]);}for(ll i=1;i<=n;i++){scanf("%lld",&val[i]);sum[i]=sum[i-1]+val[i];}query();cout<<out[1][n]<<endl;} }

?

odd-even number

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5898

題意:

給你一個區(qū)間,問你這個區(qū)間中滿足連續(xù)的偶數(shù)的位數(shù)為奇數(shù),連續(xù)的奇數(shù)的位數(shù)是偶數(shù)的個數(shù)

題解:

設(shè)dp[i][j][k][l]為考慮當前第i位,上一位的奇偶性為j,已經(jīng)連續(xù)了k位,是否有前導(dǎo)零

然后記憶化搜就行了

#include<bits/stdc++.h> #define F(i,a,b) for(int i=a;i<=b;++i) using namespace std; typedef long long ll;int dig[20],len; ll dp[20][2][20][2];ll dfs(int pos,int pre=0,int ln=0,bool inf=1,bool ze=1)//pre 1為奇;0為偶,ze是否有前導(dǎo)零 1代表有,0沒有;inf判斷當前位最大值 1表示最大值為dig[pos] {if(!pos)//搜索完成時,根據(jù)連續(xù)的長度和當前連續(xù)的是奇數(shù)還是偶數(shù)判斷反回1還是0 {if(pre)return (ln&1)==0;else return ln&1;}if(!inf&&dp[pos][pre][ln][ze]!=-1)return dp[pos][pre][ln][ze];int en=inf?dig[pos]:9;//當前位最大放幾//cout<<pos<<" "<<en<<endl;ll ans=0;F(i,0,en){if(i&1)//當前數(shù)為奇數(shù) {//cout<<i<<" "<<"?"<<endl;if(ze)//上一位為0的情況 {ans+=dfs(pos-1,1,1,inf&&i==en,0);}else if(pre==0)//上一位為偶數(shù),因為本次是奇數(shù),所以ln從1開始 {if(ln&1)ans+=dfs(pos-1,1,1,inf&&i==en,ze);}else if(pre==1)//上一位為奇數(shù) {ans+=dfs(pos-1,1,ln+1,inf&&i==en,ze);}}else//偶數(shù) {if(ze){if(i==0)ans+=dfs(pos-1,0,0,inf&&i==en,1);else ans+=dfs(pos-1,0,1,inf&&i==en,0);}else if(pre==0)ans+=dfs(pos-1,0,ln+1,inf&&i==en,ze);else if(pre==1){if((ln&1)==0)ans+=dfs(pos-1,0,1,inf&&i==en,ze);}}}if(!inf)dp[pos][pre][ln][ze]=ans;return ans; }int main(){int t,ic=1;ll l,r;scanf("%d",&t);while(t--){memset(dp,-1,sizeof(dp));scanf("%lld%lld",&l,&r),l--;for(len=0;l;l/=10)dig[++len]=l%10;//將數(shù)轉(zhuǎn)化為字符串但是逆序存放ll tp=dfs(len);for(len=0;r;r/=10)dig[++len]=r%10;printf("Case #%d: %lld\n",ic++,dfs(len)-tp);}return 0; }

List wants to travel

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5893

題目大意: 給出一棵樹上的兩種操作: 1.將節(jié)點a到節(jié)點b路徑上的邊權(quán)全部修改為c; 2.查詢節(jié)點a到節(jié)點b路徑上邊權(quán)的段數(shù)。 解題思路: 先進行樹鏈剖分,將問題轉(zhuǎn)化到區(qū)間上,之后統(tǒng)計段數(shù)是經(jīng)典的線段樹區(qū)間合并問題。修改操作直接修改就好了,對于查詢操作,需要注意鏈的合并,可以先求一次a與b的LCA,之后將路徑分為兩段分別查詢,最后看拼接處權(quán)值是否相同。

?

#include<bits/stdc++.h> using namespace std; #define maxn 40010 const int MAXM = 50050 ; struct Edge {int to,next;int len; }e[MAXM*2]; int first[maxn]; int top[maxn];//top[v]表示v所在的重鏈的頂端節(jié)點 int fa[maxn]; //父親節(jié)點 int deep[maxn];//深度 int num[maxn];//num[v]表示以v為根的子樹的節(jié)點數(shù) int p[maxn];//p[v]表示v與其父親節(jié)點的連邊在線段樹中的位置 int fp[maxn];//和p數(shù)組相反 int son[maxn];//重兒子 int pos,tot,Lc,Rc; int c[maxn],a[maxn]; void add(int u,int v,int len) {tot++;e[tot].next=first[u];e[tot].to=v;e[tot].len=len;first[u]=tot; } void dfs1(int u,int pre,int d) //第一遍dfs求出fa,deep,num,son {deep[u] = d;fa[u] = pre;num[u] = 1;for(int i = first[u];i != -1; i = e[i].next){int v = e[i].to;if(v != pre){a[v]=e[i].len;dfs1(v,u,d+1);num[u] += num[v];if(son[u] == -1 || num[v] > num[son[u]])son[u] = v;}} } void getpos(int u,int sp) //第二遍dfs求出top和p {top[u] = sp;if(son[u] != -1){p[u] = ++pos;fp[p[u]] = u;c[pos]=a[u];getpos(son[u],sp);}else{p[u] = ++pos;fp[p[u]] = u;c[pos]=a[u];return;}for(int i = first[u] ; i != -1; i = e[i].next){int v = e[i].to;if(v != son[u] && v != fa[u])getpos(v,v);} }//線段樹 struct Node {int l,r;int num;int cl,cr;int flag; }segTree[MAXM*3]; void push_up(int i) {segTree[i].cl=segTree[i<<1].cl;segTree[i].cr=segTree[i<<1|1].cr;segTree[i].num=segTree[i<<1].num+segTree[i<<1|1].num;if(segTree[i<<1].cr==segTree[i<<1|1].cl)segTree[i].num--; } void push_down(int i){if(segTree[i].flag==1){segTree[i<<1].flag=segTree[i<<1|1].flag=1;segTree[i<<1].cl=segTree[i<<1].cr=segTree[i<<1|1].cl=segTree[i<<1|1].cr=segTree[i].cl;segTree[i<<1].num=segTree[i<<1|1].num=1;segTree[i].flag=-1;} } void build(int i,int l,int r) {segTree[i].l = l;segTree[i].r = r;segTree[i].flag=-1;if(l == r){segTree[i].cl=segTree[i].cr=c[l];segTree[i].num=1;return ;}int mid = (l+r)/2;build(i<<1,l,mid);build((i<<1)|1,mid+1,r);push_up(i); }void update(int l,int r,int color,int i) {if(segTree[i].l == l && segTree[i].r == r){segTree[i].num=1;segTree[i].flag=1;segTree[i].cl=segTree[i].cr=color;return;}push_down(i);int mid = (segTree[i].l + segTree[i].r)/2;if(r <= mid)update(l,r,color,i<<1);else if(l>mid) update(l,r,color,i<<1|1);else{update(l,mid,color,i<<1);update(mid+1,r,color,i<<1|1);}push_up(i); } int query(int l,int r,int i,int L,int R) {if(segTree[i].l == L )Lc=segTree[i].cl;if(segTree[i].r==R)Rc=segTree[i].cr;if(segTree[i].l==l&&segTree[i].r==r){return segTree[i].num;}push_down(i);int mid = (segTree[i].l + segTree[i].r)/2;if(r <= mid)return query(l,r,i<<1,L,R);else if(l > mid)return query(l,r,i<<1|1,L,R);else{int num=query(l,mid,i<<1,L,R)+query(mid+1,r,i<<1|1,L,R);if(segTree[i<<1].cr==segTree[i<<1|1].cl)num--;return num;} } int solve(int u,int v) {int f1 = top[u], f2 = top[v];int tmp = 0;int pre1=-1,pre2=-1;while(f1 != f2){if(deep[f1] < deep[f2]){swap(pre1,pre2);swap(f1,f2);swap(u,v);}tmp +=query(p[f1],p[u],1,p[f1],p[u]);if(pre1==Rc)tmp--;pre1=Lc;u = fa[f1]; f1 = top[u];}if(u!=v){if(deep[u]<deep[v]){swap(pre1,pre2);swap(u,v);}tmp+=query(p[son[v]],p[u],1,p[son[v]],p[u]);if(pre1!=-1 && Rc==pre1)tmp--;if(pre2!=-1 && Lc==pre2)tmp--;}else if(pre1==pre2)tmp--;return tmp; }void gengxin(int u,int v,int value) {int f1,f2;f1=top[u];f2=top[v];while(f1!=f2){if(deep[f1]<deep[f2]){swap(f1,f2);swap(u,v);}update(p[f1],p[u],value,1);u=fa[f1];f1=top[u];}if(deep[u]<deep[v]){swap(u,v);}if(u!=v){update(p[son[v]],p[u],value,1);} } int main() {int i,j,n,m,u,v,f,g,h,w;char s[10];while(scanf("%d%d",&n,&m)!=EOF){memset(first,-1,sizeof(first));memset(son,-1,sizeof(son));pos=0;tot=0;for(i=1;i<=n-1;i++){scanf("%d%d%d",&u,&v,&w);add(u,v,w);add(v,u,w);}dfs1(1,0,1);getpos(1,1);build(1,1,pos);for(i=1;i<=m;i++){scanf("%s",s);if(s[0]=='Q'){scanf("%d%d",&f,&g);printf("%d\n",solve(f,g));}else{scanf("%d%d%d",&f,&g,&h);gengxin(f,g,h);}}}return 0; }

?

轉(zhuǎn)載于:https://www.cnblogs.com/137033036-wjl/p/6031576.html

總結(jié)

以上是生活随笔為你收集整理的2016 ACM/ICPC Asia Regional Shenyang Online的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。