I:QSC and Master

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

题意:

  给出n对数keyi,vali表示当前这对数的键值和权值,可以操作将连续的两个数合并,如果满足gcd(a[i],a[i+1])>1,得到的价值是两个数的权值和,每次合并两个数之后,这两个数就会消失,然后旁边的数会接上比如1 2 3 4 合并了 2 3 则 剩下1 4也可以合并

思路:区间dp

1:处理出任意区间内的所有数是否可以合并

对于当前的[l,r]区间,如果区间[l+1,r-1]可以合并,且gcd(a[l]+a[r])!=1的话,则整个区间[l,r]可以合并,价值也就是前缀和

同理处理出其他的情况  [l,r-2] [l+1,r]

2:区间dp,对于当前的l,r区间,如果可以合并,则直接加上区间和

反之,则枚举一个中间值k,找出区间内最大满足情况的值

#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]);}}}}
}
//判断区间是否能合并
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

题意:

给你一个区间,问你这个区间中满足连续的偶数的位数为奇数,连续的奇数的位数是偶数的个数

题解:

设dp[i][j][k][l]为考虑当前第i位,上一位的奇偶性为j,已经连续了k位,是否有前导零

然后记忆化搜就行了

#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是否有前导零 1代表有,0没有;inf判断当前位最大值 1表示最大值为dig[pos]
{if(!pos)//搜索完成时,根据连续的长度和当前连续的是奇数还是偶数判断反回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)//当前数为奇数
        {//cout<<i<<" "<<"?"<<endl;if(ze)//上一位为0的情况
            {ans+=dfs(pos-1,1,1,inf&&i==en,0);}else if(pre==0)//上一位为偶数,因为本次是奇数,所以ln从1开始
            {if(ln&1)ans+=dfs(pos-1,1,1,inf&&i==en,ze);}else if(pre==1)//上一位为奇数
            {ans+=dfs(pos-1,1,ln+1,inf&&i==en,ze);}}else//偶数
        {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;//将数转化为字符串但是逆序存放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.将节点a到节点b路径上的边权全部修改为c;
2.查询节点a到节点b路径上边权的段数。
解题思路:
先进行树链剖分,将问题转化到区间上,之后统计段数是经典的线段树区间合并问题。修改操作直接修改就好了,对于查询操作,需要注意链的合并,可以先求一次a与b的LCA,之后将路径分为两段分别查询,最后看拼接处权值是否相同。
#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所在的重链的顶端节点
int fa[maxn]; //父亲节点
int deep[maxn];//深度
int num[maxn];//num[v]表示以v为根的子树的节点数
int p[maxn];//p[v]表示v与其父亲节点的连边在线段树中的位置
int fp[maxn];//和p数组相反
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;
}

转载于:https://www.cnblogs.com/137033036-wjl/p/6031576.html

2016 ACM/ICPC Asia Regional Shenyang Online相关推荐

  1. Problem 1002-2017 ACM/ICPC Asia Regional Shenyang Online

    网络赛:2017 ACM/ICPC Asia Regional Shenyang Online 题目来源:cable cable cable Problem Description: Connecti ...

  2. 2015 ACM/ICPC Asia Regional Shenyang Online题解

    以下所有AC题解程序来自"仙客传奇"团队. AC题数:7/13 ABCFGJL A. Traversal AC的C++语言程序: #include <bits/stdc++. ...

  3. 2016 ACM/ICPC Asia Regional Qingdao Online 1005 Balanced Game

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5882 Problem Description Rock-paper-scissors is a ze ...

  4. 2017 ACM/ICPC Asia Regional Shenyang Online array

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=6197 题目大意:给出一个序列,删去k个元素是否能构成不上升序列或不下降子序列 (呃,先凑个数吧 二分+ ...

  5. 2017 ACM/ICPC Asia Regional Shenyang Online Ping Ping Ping 树链剖分+树状数组

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=6203 题目大意:给出n+1个节点的树( 3<n<10^4),并给出m对点(m<=50 ...

  6. 2016 ACM/ICPC Asia Regional Dalian Online

    1009 Sparse Graph(hdu5876) 由于每条边的权值都为1,所以最短路bfs就够了,只是要求转置图的最短路,所以得用两个set来维护,一个用来存储上次扩散还没访问的点,一个用来存储这 ...

  7. [Contest]2017 ACM/ICPC Asia Regional Shenyang Online(01 03 07 09 10 11待补)

    1001 string string string 题意 给定一个字符串$s$,求其中出现$k$次的子串的个数. 题解 后缀自动机. 代码 1002 cable cable cable 题意 给定$M ...

  8. HDU 6194 String String String (后缀数组+线段树, 2017 ACM/ICPC Asia Regional Shenyang Online)

    Problem 求字符串 S 中严格出现 k 次的子串个数 k≥1k\ge 1 |S|≤105|S|\le 10^5 ∑|S|≤2×106\sum |S| \le 2\times 10^6 Idea ...

  9. Hdu 5873 2016 ACM/ICPC Asia Regional Dalian Online 1006(兰道定理)

    题解: 如果没有平手选项, 赢得加一分的话, 可以用Landau's Theorem(兰道定理)判定. 稍微修改一下这个定理就能做了. 假设S1,S2--,Sn是他们的得分序列,从小到大排个序.那么这 ...

最新文章

  1. JMS配置说明-----activeMQ-5.6
  2. javaweb功能模块如何合理设计_产品设计:如何设计出合理的凑单模式?
  3. php数组能不能静态,php 为什么常量可以用数组定义 静态变量却不能
  4. 在CentOS中安装NodeJS
  5. 如何把程序挂在远端服务器python_Pycharm连接远程服务器并实现远程调试的实现...
  6. ELK + kafka 分布式日志解决方案
  7. 问题解决:pip无法使用,经升级后可以使用
  8. jquery详细基础教程
  9. 洛谷 3951 小凯的疑惑
  10. Linux内核专题 - 介绍
  11. adams2020安装教程(附详细图文安装教程)
  12. vue判断设备是手机端还是pc端
  13. uniapp 分享缩略图过大怎么办_uniapp 选择并压缩图片
  14. 会计核算的基本前提与确认计量的一般原则
  15. 【Linux】管道实现进程间通信
  16. java hypot_Java StrictMath hypot()用法及代碼示例
  17. html td 的横向与纵向合并
  18. Hadoop/Hive-学习笔记【中级篇】
  19. java判断时间段是否交叉重叠
  20. 总结2018,规划2019

热门文章

  1. Everyday English
  2. 算法实验--主函数只有五行的Floyed的算法以及最短路径输出
  3. 行为型模式:模板方法
  4. 如何玩转跨库Join?跨数据库实例查询应用实践
  5. 22.6. 视图(View)
  6. “六神”——技术提高开发效率的一个方案
  7. win10 中的eclipse无法新建web项目
  8. Bootstrap系列 -- 34. 按钮下拉菜单
  9. Javascript事件模型系列(二)事件的捕获-冒泡机制及事件委托机制
  10. MySQL Workbench 5.2.45 GA 发布