博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2015 Multi-University Training Contest 3
阅读量:5078 次
发布时间:2019-06-12

本文共 7506 字,大约阅读时间需要 25 分钟。

1001 

线段树。根据奇偶性分成4个区间。维护子列和最大值。

想法很简单。但是并不好写。

首先初始化的时候对于不存在的点要写成-INF。

然后pushup的时候。对于每个区间要考虑四个情况。

例如sum01。

他可能是左子树的sum01右子树的sum01。

或者左子树的sum01+右子树的sum01。

或者左子树的sum00+右子树的sum11。

最后注意query函数的写法。

如果在递归的时候就讨论奇偶性。

下层的每个区间都要被重复调用。而且是层数的指数级。

于是参考学习了一种直接把子区间合并成一个区间类型返回的方法。

合成目标区间后再讨论奇偶性。

【其实pushup和query可以写好看些。好不容易调对。懒得改了。】

1 # include 
2 # include
3 # include
4 using namespace std; 5 typedef long long LL; 6 # define maxn 100010 7 # define INF (LL)1000000000000 8 LL a[maxn]; 9 10 struct node 11 { 12 int l,r; 13 LL sum00,sum01,sum10,sum11; 14 }tree[4*maxn]; 15 16 void pushup(int i) 17 { 18 tree[i].sum00=tree[i].sum01=tree[i].sum10=tree[i].sum11=-INF; 19 tree[i].sum00=max(tree[i].sum00,tree[2*i].sum00+tree[2*i+1].sum10); 20 tree[i].sum00=max(tree[i].sum00,tree[2*i].sum01+tree[2*i+1].sum00); 21 tree[i].sum00=max(tree[i].sum00,tree[2*i].sum00); 22 tree[i].sum00=max(tree[i].sum00,tree[2*i+1].sum00); 23 tree[i].sum01=max(tree[i].sum01,tree[2*i].sum00+tree[2*i+1].sum11); 24 tree[i].sum01=max(tree[i].sum01,tree[2*i].sum01+tree[2*i+1].sum01); 25 tree[i].sum01=max(tree[i].sum01,tree[2*i].sum01); 26 tree[i].sum01=max(tree[i].sum01,tree[2*i+1].sum01); 27 tree[i].sum10=max(tree[i].sum10,tree[2*i].sum10+tree[2*i+1].sum10); 28 tree[i].sum10=max(tree[i].sum10,tree[2*i].sum11+tree[2*i+1].sum00); 29 tree[i].sum10=max(tree[i].sum10,tree[2*i].sum10); 30 tree[i].sum10=max(tree[i].sum10,tree[2*i+1].sum10); 31 tree[i].sum11=max(tree[i].sum11,tree[2*i].sum10+tree[2*i+1].sum11); 32 tree[i].sum11=max(tree[i].sum11,tree[2*i].sum11+tree[2*i+1].sum01); 33 tree[i].sum11=max(tree[i].sum11,tree[2*i].sum11); 34 tree[i].sum11=max(tree[i].sum11,tree[2*i+1].sum11); 35 return; 36 } 37 38 void buildtree(int i,int l,int r) 39 { 40 tree[i].l=l; tree[i].r=r; 41 if(l
=l&&tree[i].r<=r) return tree[i]; 82 if(r<=(tree[i].l+tree[i].r)/2) return query(2*i,l,r); 83 if(l>=(tree[i].l+tree[i].r)/2+1) return query(2*i+1,l,r); 84 node t,t1,t2; 85 t1=query(2*i,l,r); 86 t2=query(2*i+1,l,r); 87 t.sum00=max(t1.sum00,t2.sum00); 88 t.sum00=max(t.sum00,t1.sum00+t2.sum10); 89 t.sum00=max(t.sum00,t1.sum01+t2.sum00); 90 t.sum01=max(t1.sum01,t2.sum01); 91 t.sum01=max(t.sum01,t1.sum00+t2.sum11); 92 t.sum01=max(t.sum01,t1.sum01+t2.sum01); 93 t.sum10=max(t1.sum10,t2.sum10); 94 t.sum10=max(t.sum10,t1.sum10+t2.sum10); 95 t.sum10=max(t.sum10,t1.sum11+t2.sum00); 96 t.sum11=max(t1.sum11,t2.sum11); 97 t.sum11=max(t.sum11,t1.sum10+t2.sum11); 98 t.sum11=max(t.sum11,t1.sum11+t2.sum01); 99 return t;100 }101 102 int main(void)103 {104 int T; cin>>T;105 while(T--)106 {107 int n,m; scanf("%d%d",&n,&m);108 for(int i=1;i<=n;i++) scanf("%I64d",a+i);109 buildtree(1,1,n);110 while(m--)111 {112 int type,x,y; scanf("%d%d%d",&type,&x,&y);113 if(type) update(1,x,y);114 else115 {116 node tem=query(1,x,y);117 LL ans=-INF;118 ans=max(ans,tem.sum00);119 ans=max(ans,tem.sum01);120 ans=max(ans,tem.sum10);121 ans=max(ans,tem.sum11);122 printf("%I64d\n",ans);123 }124 } 125 }126 return 0;127 }
Aguin

 

 

1002 

先枚举1000000内所有质因数。

然后统计区间内每个数的质因数个数。

注意到最大只有7。

对于因子个数为1-7的数的个数处理一下前缀和。

对于每个询问。算区间内因子数分别为1-7的数的个数。

找到最大的gcd就是答案。

1 # include 
2 # include
3 # include
4 # include
5 # include
6 using namespace std; 7 # define maxn 1000010 8 bool tag[maxn]={
1,1}; 9 int prime[42000],cnt[maxn]={
0},presum[8][maxn]={
0};10 11 int main(void)12 {13 int t=0;14 for(int i=2;i
>T;33 while(T--)34 {35 int l,r; scanf("%d%d",&l,&r);36 int mark[8]={ 0};37 for(int i=1;i<8;i++) mark[i]=max(0,presum[i][r]-presum[i][l-1]);38 if(mark[7]>=2) printf("7\n");39 else if(mark[6]>=2) printf("6\n");40 else if(mark[5]>=2) printf("5\n");41 else if(mark[4]>=2) printf("4\n");42 else if(mark[3]>=2||mark[3]&&mark[6]) printf("3\n");43 else if(mark[2]>=2||mark[2]&&mark[4]||mark[2]&&mark[6]) printf("2\n");44 else printf("1\n");45 }46 return 0; 47 }
Aguin

 

 

1003 

 

1004 

看成R和B的两张图。

统计R\斜边上与B/斜边上的连续染色段数即为答案。

1 # include 
2 # include
3 # include
4 using namespace std; 5 # define CLR(x) memset(x,0,sizeof(x)) 6 char map[55][55]; 7 int R[55][55],B[55][55]; 8 9 int main(void)10 {11 int T; cin>>T;12 while(T--)13 {14 CLR(map); CLR(R); CLR(B);15 int n; scanf("%d",&n);16 for(int i=0;i
=0;j++)40 {41 if(i-j>=n) continue;42 if(!flag&&B[i-j][j]) {ans++;flag=1;}43 if(!B[i-j][j]) flag=0;44 }45 }46 printf("%d\n",ans);47 }48 return 0;49 }
Aguin

 

 

1005 

 

1006 

 

1007 

 

1008 

暴搜可行 证明不会。

l<0跳。l>r-l跳。r>现有答案跳。

搜[l,2*r-l]的时候注意死循环。

1 # include 
2 # include
3 # include
4 using namespace std; 5 typedef long long LL; 6 LL ans; 7 8 void dfs(LL l,LL r) 9 {10 if(l==0)11 {12 if(ans==-1) ans=r;13 else ans=min(ans,r);14 return;15 }16 if(l<0) return;17 if(ans!=-1&&r>=ans) return;18 if(r>2*l) return;19 if(r>l) dfs(l,2*r-l);20 dfs(2*l-r-1,r);21 dfs(2*l-r-2,r);22 dfs(l,2*r-l+1);23 return;24 }25 26 int main(void)27 {28 LL l,r;29 while((scanf("%I64d%I64d",&l,&r))!=EOF)30 {31 ans=-1;32 dfs(l,r);33 printf("%I64d\n",ans);34 }35 return 0;36 }
Aguin

 

 

1009 

 

1010 

按官方题解。

把每条边变成从w大的点到w小的点的有像边。 

以u为min的目标集就是能走到u的点的集合。

花了较长的时间思考这个问题。

换一种说法。

其实就是对于一个已经确定最小值u的目标集S。

点v在S中当且仅当v能通过递减的路到达u。

简要说明一下必要性和充分性。

随手画了个图。

任意取一条链。比方X。它必然有一个端点x1。

只要说明离x1最近的点x2小于x1。然后考虑去掉x1的图。归纳即可得到上述结论。

考虑S中比x1小的最大的点p的位置。

如果x2就是p。那么它比x1小。

如果x2不是p。那么由于x2离x1最近。无论p在什么位置。x2都在p-x1的链上。

根据S的定义。x2小于x1。

反之。如果所有链都是以递减的顺序通向u的。

那么考虑图中的最大点。其必然在一条链的端点。

比方仍取X链。x1是最大点。

最大点给集合带来的约束条件只有一条。

那就是最大点到次大点的路径上的所有点小于最大点。

但是所有点都小于最大点。所以这个条件必然成立。

也就是说原来的点属于S集等价于去掉最大点后的所有点属于S集合。

而去掉x1后的最大点可能是x2或者是其他链的端点。

只要不断从端点去掉最大点。归纳即可证明原来的所有点属于S集。

证明这个之后。树dp即可。

1 # include 
2 # include
3 # include
4 # include
5 # include
6 using namespace std; 7 # define maxn 500050 8 int w[maxn],dp[maxn]; 9 vector
edge[maxn];10 11 struct V12 {13 int id,w;14 } node[maxn];15 16 bool cmp(V a,V b)17 {18 return a.w>b.w;19 }20 21 int main(void)22 {23 int n;24 while((scanf("%d",&n))!=EOF)25 {26 memset(edge,0,sizeof(edge));27 for(int i=1;i<=n;i++)28 {29 scanf("%d",w+i);30 node[i].id=i;31 node[i].w=w[i];32 }33 for(int i=1;i
w[b]) edge[b].push_back(a);37 else if(w[a]
Aguin

 

 

1011 

签到题。dfs一遍即可。

1 # include 
2 # include
3 # include
4 # include
5 using namespace std; 6 int ind[105],cnt[105]; 7 vector
edge[105]; 8 9 void dfs(int x)10 {11 cnt[x]=edge[x].size();12 for(int i=0;i
Aguin

 

转载于:https://www.cnblogs.com/Aguin/p/4683494.html

你可能感兴趣的文章
python的列表与shell的数组
查看>>
关于TFS2010使用常见问题
查看>>
软件工程团队作业3
查看>>
python标准库——queue模块 的queue类(单向队列)
查看>>
火狐、谷歌、IE关于document.body.scrollTop和document.documentElement.scrollTop 以及值为0的问题...
查看>>
深入理解JVM读书笔记--字节码执行引擎
查看>>
vue-搜索功能-实时监听搜索框的输入,N毫秒请求一次数据
查看>>
批处理 windows 服务的安装与卸载
查看>>
React文档翻译 (快速入门)
查看>>
nodejs fs路径
查看>>
动态规划算法之最大子段和
查看>>
linux c:关联变量的双for循环
查看>>
深入浅出理解zend framework(三)
查看>>
python语句----->if语句,while语句,for循环
查看>>
javascript之数组操作
查看>>
LinkedList源码分析
查看>>
TF-IDF原理
查看>>
用JS制作博客页面背景随滚动渐变的效果
查看>>
JavaScript的迭代函数与迭代函数的实现
查看>>
一步步教你学会browserify
查看>>