热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【CQOI2016纯净整合】BZOJ-4519~4524(6/6)

感觉CQOI的难度挺好的,比较贴近自身,所以拿出来做了一下CQOI2016Day1T1:不同的最小割涉及算法:最小割分治最小割树思路:最小割树裸题,直接分治最小割,记录下答案

感觉CQOI的难度挺好的,比较贴近自身,所以拿出来做了一下


 

 

CQOI2016 Day1 T1:不同的最小割

涉及算法:最小割/分治/最小割树

思路:

最小割树裸题,直接分治最小割,记录下答案,最后排序一下,统计不同的答案即可

CODE:

#include
#include

#include

#include

#include

using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
#define maxn 1000
#define maxm 100010
int n,m,q,t,ans[maxn],tot,id[maxn],tmp[maxn];
struct Edgenode{int next,to,cap;}edge[maxm];
int head[maxn],cnt=1;
void add(int u,int v,int w)
{cnt
++; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].cap=w;}
void insert(int u,int v,int w) {add(u,v,w); add(v,u,w);}
int dis[maxn],que[maxn<<1],cur[maxn],S,T;
bool bfs()
{
memset(dis,
-1,sizeof(dis));
que[
0]=S; dis[S]=0; int he=0,ta=1;
while (he<ta)
{
int now=que[he++];
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==-1)
dis[edge[i].to]
=dis[now]+1,que[ta++]=edge[i].to;
}
return dis[T]!=-1;
}
int dfs(int loc,int low)
{
if (loc==T) return low;
int w,used=0;
for (int i=cur[loc]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==dis[loc]+1)
{
w
=dfs(edge[i].to,min(low-used,edge[i].cap));
edge[i].cap
-=w; edge[i^1].cap+=w;
used
+=w; if (edge[i].cap) cur[loc]=i;
if (used==low) return low;
}
if (!used) dis[loc]=-1;
return used;
}
#define inf 0x7fffffff
int dinic()
{
int tmp=0;
while (bfs())
{
for (int i=1; i<=n; i++) cur[i]=head[i];
tmp
+=dfs(S,inf);
}
return tmp;
}
void init()
{
cnt
=1;
memset(ans,
0,sizeof(ans));
memset(head,
0,sizeof(head));
}
bool visit[maxn];
void DFS(int x)
{
visit[x]
=1;
for (int i=head[x]; i; i=edge[i].next)
if (edge[i].cap && !visit[edge[i].to])
DFS(edge[i].to);
}
void work(int L,int R)
{
if (L==R) return;
for (int i=2; i<=cnt; i+=2)
edge[i].cap
=edge[i^1].cap=(edge[i].cap+edge[i^1].cap)>>1;
S
=id[L],T=id[R];
int maxflow=dinic();
memset(visit,
0,sizeof(visit)); DFS(S);
// for (int i=1; i<=n; i++) if (visit[i])
// for (int j=1; j<=n; j++) if (!visit[j])
// ans[i][j]=ans[j][i]=min(ans[i][j],maxflow);
ans[++tot]=maxflow;
int l=L,r=R;
for (int i=L; i<=R; i++)
if (visit[id[i]])
tmp[l
++]=id[i];
else tmp[r--]=id[i];
for (int i=L; i<=R; i++) id[i]=tmp[i];
work(L,l
-1); work(r+1,R);
}
int main()
{
// freopen("mincuto.in","r",stdin);
// freopen("mincuto.out","w",stdout);
init();
n
=read(),m=read();
for (int i=1; i<=n; i++) id[i]=i;
for (int u,v,w,i=1; i<=m; i++)
u
=read(),v=read(),w=read(),insert(u,v,w);
work(
1,n);
sort(ans
+1,ans+tot+1);
int an=1;
for (int i=2; i<=tot; i++) if (ans[i]!=ans[i-1]) an++;
printf(
"%d\n",an);
return 0;
}
Day1T1

 

 


 

 

CQOI2016 Day1 T2:K远点对

涉及算法:凸包/KD-Tree/可并堆

思路:

先把所有点都放到KD Tree里,维护一个小根堆,枚举每个点。每次在kd树种查询的时候,就相当于当前的最优解是堆顶,像查最远点对一样在kd树里查就行了。 

CODE:

#include
#include

#include

#include

#include

#include

#include

using namespace std;
long long read()
{
long long x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define maxn 100010
#define inf 100000000000000000LL
int n,k,D;
long long sqr(long long a) {return (long long)(a*a);}
struct PointNode
{
int l,r; long long d[2],maxx[2],minn[2];
bool operator <(const PointNode & A) const {return d[D]<A.d[D];}
PointNode (
long long x=0,long long y=0) {l=r=0; d[0]=x; d[1]=y;}
}p[maxn];
priority_queue
<long long, vector<long long>, greater<long long> > heap;
long long dis(PointNode A,PointNode B) {return sqr(A.d[1]-B.d[1])+sqr(A.d[0]-B.d[0]);}
struct KDTreeNode
{
int rt;
PointNode Point,tree[maxn
<<1];
void Update(int now)
{
for (int i=0; i<=1; i++)
{
tree[now].minn[i]
=tree[now].maxx[i]=tree[now].d[i];
if (tree[now].l)
tree[now].minn[i]
=min(tree[tree[now].l].minn[i],tree[now].minn[i]),tree[now].maxx[i]=max(tree[tree[now].l].maxx[i],tree[now].maxx[i]);
if (tree[now].r)
tree[now].minn[i]
=min(tree[tree[now].r].minn[i],tree[now].minn[i]),tree[now].maxx[i]=max(tree[tree[now].r].maxx[i],tree[now].maxx[i]);
}
}
int BuildTree(int l,int r,int dd)
{
int mid=(l+r)>>1;
D
=dd; nth_element(p+l,p+mid,p+r+1);
tree[mid]
=p[mid];
for (int i=0; i<=1; i++) tree[mid].minn[i]=tree[mid].maxx[i]=tree[mid].d[i];
if (l1,dd^1);
if (r>mid) tree[mid].r=BuildTree(mid+1,r,dd^1);
Update(mid);
return mid;
}
long long dist(int pl,PointNode P)
{
long long re=0;
for (int i=0; i<=1; i++)
re
+=max(sqr(P.d[i]-tree[pl].minn[i]),sqr(P.d[i]-tree[pl].maxx[i]));
return re;
}
void Query(int now)
{
long long dl,dr,d0;
d0
=dis(tree[now],Point);
if (d0>heap.top()) heap.pop(),heap.push(d0);
if (tree[now].l) dl=dist(tree[now].l,Point); else dl=-inf;
if (tree[now].r) dr=dist(tree[now].r,Point); else dr=-inf;
if (dl>dr)
{
if (dl>heap.top()) Query(tree[now].l);
if (dr>heap.top()) Query(tree[now].r);
}
else
{
if (dr>heap.top()) Query(tree[now].r);
if (dl>heap.top()) Query(tree[now].l);
}
}
}KDTree;
int main()
{
// freopen("farthest.in","r",stdin);
// freopen("farthest.out","w",stdout);
n=read(); k=read();
for (int x,y,i=1; i<=n; i++) x=read(),y=read(),p[i]=PointNode(x,y);
KDTree.rt
=KDTree.BuildTree(1,n,0);
for (int i=1; i<=k+k; i++) heap.push(0LL);
for (int i=1; i<=n; i++)
KDTree.Point
=p[i],KDTree.Query(KDTree.rt);
printf(
"%lld\n",heap.top());
return 0;
}
Day1T2

 

 


 

 

CQOI2016 Day1 T3:手机号码

涉及算法:数位DP/记忆化搜索

思路:

涉及F[i][j][0/1][0/1][0/1][0/1][0/1]表示位数为i,最高位为j,最高位连续两个是否是相同的,是否有连续3个相同的,是否有4,是否有8,前缀和原数前缀的大小关系

枚举k1,k2,k3,k4,k5转移统计答案即可,注意一些细节(记忆化搜索应该比较好实现)

CODE:

#include
#include

#include

#include

using namespace std;
long long F[20][15][2][2][2][2][2],l,r;
int p[20],num;
long long cal(long long x)
{
memset(F,
0,sizeof(F));
long long ans=0; int len=0,digit[12],a,b,c,d,e;
while(x){digit[++len]=x%10; x/=10;}
reverse(digit
+1,digit+len+1);
F[
0][10][0][0][0][0][1]=1;
for (int i=0; i<=len-1; i++)
for (int j=0; j<=10; j++)
for (int k1=0; k1<=1; k1++)
for (int k2=0; k2<=1; k2++)
for (int k3=0; k3<=1; k3++)
for (int k4=0; k4<=1; k4++)
for (int k5=0; k5<=1; k5++)
if (F[i][j][k1][k2][k3][k4])
for (int k=0; k<=9; k++)
{
if (k5 && (k>digit[i+1])) continue;
if (k==j) a=1; else a=0;
if (k2==0) b=(k1+a)==2; else b=k2;
if (k3==0) c=(k==4); else c=k3;
if (k4==0) d=(k==8); else d=k4;
if ((c+d)==2) continue;
if (k5 && (k==digit[i+1])) e=1; else e=0;
F[i
+1][k][a][b][c][d][e]+=F[i][j][k1][k2][k3][k4][k5];
}
for (int i=0; i<=9; i++)
for (int k1=0; k1<=1; k1++)
for (int k3=0; k3<=1; k3++)
for (int k4=0; (k4<=1)&&(k4+k3<2); k4++)
ans
+=F[len][i][k1][1][k3][k4][0];
return ans;
}
int main()
{
scanf(
"%lld%lld",&l,&r);
printf(
"%lld\n",cal(r+1)-cal(l));
return 0;
}
Day1T3

 


 

 

CQOI2016 Day2 T1:密钥破解

涉及算法:数论/Pollard_Rho分解/ExGcd/乘法逆元/快速幂/快速乘/模拟

思路:

用Pollard_Rho分解N,得到P,Q,同时计算出r;剩下的根据题意模拟

利用ExGcd求解e在r意义下的逆元,最后答案用快速幂算出即可

CODE:

#include
#include

#include

#include

#include

#include

using namespace std;
long long read()
{
long long x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
long long e,N,c,r,P,Q;
long long Quick_Mul(long long x,long long y,long long p)
{
long long re=0;
for (long long i=y; i; i>>=1,x=(x+x)%p)
if (i&1) re=(re+x)%p;
return re;
}
long long Quick_Pow(long long x,long long y,long long p)
{
long long re=1;
for (long long i=y; i; i>>=1,x=Quick_Mul(x,x,p))
if (i&1) re=Quick_Mul(re,x,p);
return re;
}
void Exgcd(long long a,long long b,long long &x,long long &y)
{
if (b==0) {x=1; y=0; return;}
Exgcd(b,a
%b,y,x); y-=(a/b)*x;
}
long long GetInv(long long n,long long p)
{
long long x,y;
Exgcd(n,p,x,y);
return (x%p+p)%p;
}
long long Gcd(long long a,long long b)
{
if (b==0) return a;
return Gcd(b,a%b);
}
#define T 10007
long long Pollard_Rho(long long n)
{
long long x,y,cnt=1,k=2;
x
=rand()%(n-1)+1; y=x;
while (1)
{
cnt
++;
x
=(Quick_Mul(x,x,n)+T)%n;
long long gcd=Gcd(abs(x-y),n);
if (1return gcd;
if (x==y) return n;
if (cnt==k) y=x,k<<=1;
}
}
int main()
{
srand(T);
e
=read(),N=read(),c=read();
P
=Pollard_Rho(N); Q=N/P;
r
=(P-1)*(Q-1);
long long Inv=GetInv(e,r);
printf(
"%lld %lld",Inv,Quick_Pow(c,Inv,N));
return 0;
}
Day2T1

 


 

 

CQOI2016 Day2 T2:路由表

涉及算法:Trie树/单调栈/进制转化

思路:

A/Q操作都对IP进行二进制转化后进行处理

A操作将转化后的IP前掩码为加到Trie树中,结尾打上时间戳标记

Q操作,二进制在Trie树上跑跑,将答案记录下来,排序后统计一下答案即可,或者利用单调栈维护即可

CODE:

#include
#include

#include

#include

#include

using namespace std;
int m,Ip[50];
#define maxn 1000100
int ch[maxn][2],pos[maxn],rt=1,cnt=1,sz=1,ti=0;
void Insert(int *ip,int l,int x)
{
int now=rt;
for (int i=1; i<=l; i++)
{
if (!ch[now][ip[i]])
ch[now][ip[i]]
=++sz;
now
=ch[now][ip[i]];
}
pos[now]
=x;
}
struct Node
{
int a,b;
bool operator <(const Node & A) const
{
return a<A.a;}
};
Node stack[maxn];
int top;
int Query(int *ip,int L,int R)
{
int now=rt,re=0,m=-1; top=0;
for (int i=1; i<=32; i++)
{
if (!ch[now][ip[i]]) break;
now
=ch[now][ip[i]];
if (pos[now] && pos[now]<=R)
stack[
++top]=Node{pos[now],i+1};
}
sort(stack
+1,stack+top+1);
for (int i=1; i<=top; i++)
{
Node now
=stack[i];
if (mif (now.a>=L) re++;}
}
return re;
}
int main()
{
scanf(
"%d",&m);
for (int i=1; i<=m; i++)
{
char opt[5]; scanf("%s",opt);
if (opt[0]=='A')
{
ti
++; int ip,len=0,l;
memset(Ip,
0,sizeof(Ip));
for (int j=1; j<=3; j++)
{
scanf(
"%d.",&ip);
for (int k=7; k>=0; k--)
Ip[
++len]=(1&(ip>>k));

}
scanf(
"%d/",&ip);
for (int k=7; k>=0; k--) Ip[++len]=(1&(ip>>k));
scanf(
"%d",&l);
//for (int j=1; j<=len; j++) printf("%d",Ip[j]); puts("");
Insert(Ip,l,ti);
}
if (opt[0]=='Q')
{
int ip,len=0,l,r;
memset(Ip,
0,sizeof(Ip));
for (int j=1; j<=3; j++)
{
scanf(
"%d.",&ip);
for (int k=7; k>=0; k--)
Ip[
++len]=(1&(ip>>k));
}
scanf(
"%d",&ip);
for (int k=7; k>=0; k--) Ip[++len]=(1&(ip>>k));
scanf(
"%d %d",&l,&r);
//for (int j=1; j<=len; j++) printf("%d",Ip[j]); puts("");
printf("%d\n",Query(Ip,l,r));
}
}
return 0;
}
Day2T2

 


 

 

CQOI2016 Day2 T3:伪光滑数

涉及算法:可持久化可并堆/DP/堆/贪心/暴力

思路:

预处理出$<128"><128$的全部质数,那么很显然,可以对数进行拆分了.

考虑题目中所说的, 所以不妨枚举倍数,对于$prime[i]j">prime[i]^{j}$,扔进堆中

然后从队首取K次即可,对于每次取出的数,除以它的最大质因子,乘上比他最大质因子小的最大的质数,再扔回堆中

可持久化可并堆+DP的方法并不会....(留坑以后来看看)

CODE:

#include 
#include

#include

#include

using namespace std;
struct Node
{
long long data; int zs,nt,mp;
bool operator <(const Node & A) const
{
return data<A.data;}
}now,tmp;
priority_queue
q;
long long n,x; int k,j;
int prime[50]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127},cnt=31;
int main()
{
scanf(
"%lld%d",&n,&k);
for (int i=1; i<=cnt; i++)
for (x=j=1; ; j++)
{
x
*=(long long)prime[i]; if (x>n) break;
tmp.data
=x,tmp.zs=j,tmp.nt=i-1,tmp.mp=i;
//printf("%lld %d %d %d\n",tmp.data,tmp.zs,tmp.nt,tmp.mp);
q.push(tmp);
}
while (k--)
{
now
=q.top(); q.pop();
if (now.zs>1)
for (int i=now.nt; i; i--)
{
tmp.data
=(long long)now.data/prime[now.mp]*prime[i]; tmp.zs=now.zs-1; tmp.nt=i; tmp.mp=now.mp;
//printf("%lld %d %d %d\n",tmp.data,tmp.zs,tmp.nt,tmp.mp);
q.push(tmp);
}
}
printf(
"%lld\n",now.data);
return 0;
}
Day2T3

 


据azui神犇所说..CQOI都是 偏题,语文题,模板题 ...但是感觉今年的题目还是不错的,比较有价值

 

暴露的一些问题:

1.有题目可以想到正确做法,但是实现起来有差错,细节上的问题尤其容易出现

2.一些实用的算法和数据结构并不熟练,需要重视起来

3.调试的时间过长,发现问题不敏锐,严重影响进度,以后应该加强

 

启发:

1.对于想不出来最优解的问题,可以考虑想时间复杂度次优的方法,尽可能的优,在实际中能得到大把的分数,或者卡时A

2.数位DP方面需要总结一下技巧和方法,只有总结出了方法,才能面对各种题都不慌

3.认真读题,想题做题时要确保理解了题意,才能更深入的想出优秀的算法,很多时候应该按照题意去模拟

4.一些非反演的数论题,可能只是需要进行一些转化,然后多种东西嵌套求解,不用慌张;对于跟质因子相关的题目,入手点在质因子上,往往能得到高效的结果

 

 

UPD:2016.05.24Day1T2(填坑完毕),附上全家福:


推荐阅读
  • 题目解析给定 n 个人和 n 种书籍,每个人都有一个包含自己喜好的书籍列表。目标是计算出满足以下条件的分配方案数量:1. 每个人都必须获得他们喜欢的书籍;2. 每本书只能分配给一个人。通过使用深度优先搜索算法,可以系统地探索所有可能的分配组合,确保每个分配方案都符合上述条件。该方法能够有效地处理这类组合优化问题,找到所有可行的解。 ... [详细]
  • 本文介绍如何使用线段树解决洛谷 P1531 我讨厌它问题,重点在于单点更新和区间查询最大值。 ... [详细]
  • poj 3352 Road Construction ... [详细]
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
  • T15483.【清华集训2017模拟11.26】简单路径T25484.【清华集训2017模拟11.26】快乐树T35485.【清华集训2017模拟11.26】字符串T1结论题,结论很 ... [详细]
  • 数据结构第三章,栈、队列、数组,期末不挂科指南,第3篇
    数据结构第三章,栈、队列、数组,期末不挂科指南,第3篇,Go语言社区,Golang程序员人脉社 ... [详细]
  • Halcon之图像梯度、图像边缘、USM锐化
    图像梯度、图像边缘、USM锐化图像梯度、图像边缘、USM锐化图像梯度、图像边缘、USM锐化图像卷积:1.模糊2.梯度3.边缘4.锐化1.视频教程:B站、 ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4277。作者:Bob Lee,日期:2012年9月15日。题目描述:给定n个木棍,求可以组成的不同三角形的数量,最多15根木棍。 ... [详细]
  • 题目《BZOJ2654: Tree》的时间限制为30秒,内存限制为512MB。该问题通过结合二分查找和Kruskal算法,提供了一种高效的优化解决方案。具体而言,利用二分查找缩小解的范围,再通过Kruskal算法构建最小生成树,从而在复杂度上实现了显著的优化。此方法不仅提高了算法的效率,还确保了在大规模数据集上的稳定性能。 ... [详细]
  • 本报告对2018年湘潭大学程序设计竞赛在牛客网上的时间数据进行了详细分析。通过统计参赛者在各个时间段的活跃情况,揭示了比赛期间的编程频率和时间分布特点。此外,报告还探讨了选手在准备过程中面临的挑战,如保持编程手感、学习逆向工程和PWN技术,以及熟悉Linux环境等。这些发现为未来的竞赛组织和培训提供了 valuable 的参考。 ... [详细]
  • 本文提出了一种基于栈结构的高效四则运算表达式求值方法。该方法能够处理包含加、减、乘、除运算符以及十进制整数和小括号的算术表达式。通过定义和实现栈的基本操作,如入栈、出栈和判空等,算法能够准确地解析并计算输入的表达式,最终输出其计算结果。此方法不仅提高了计算效率,还增强了对复杂表达式的处理能力。 ... [详细]
  • 作文记录:合并区间的技巧与应用
    本文详细记录了合并区间问题的解题技巧与应用场景。首先介绍了问题背景和题目描述,接着从排序最大值的角度探讨了解决思路,并提供了具体的程序代码及运行结果。此外,还探讨了其他可能的解决方案。最后,对整个解题过程进行了总结,为读者提供了全面的理解和参考。 ... [详细]
  • 本文是Java并发编程系列的开篇之作,将详细解析Java 1.5及以上版本中提供的并发工具。文章假设读者已经具备同步和易失性关键字的基本知识,重点介绍信号量机制的内部工作原理及其在实际开发中的应用。 ... [详细]
author-avatar
血玉残阳
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有