您的位置:首页 > 理论基础 > 计算机网络

2015 acm/icpc上海站网络赛个人小结

2015-11-10 15:59 645 查看
这场比赛打得迷一样,看完题目就觉得自己的智商下降了好多,自己的算法学和不学差不了太多。

1001

表示一开始看到就感觉是线段树,可是个人表示这个线段树的处理表示不是那么会,因为涉及到树的搜索以及预处理(预处理是因为数据量),本人书上的搜索渣的不要不要的。所以还不是很会。

1002~1004

都看懂题意了,都不会。

1005

做这题的人简直就是给自己找罪受,队友模拟了整个比赛的时间还愣是WA,也是醉了,赛后去看了hdoj的解决人数,少的可以。至今还WA。

1006~1007

前者是凸包模板再加上dp,后者连要干嘛都看不懂。。

1008

这倒是一道比较简单的线段树题,没有像1001那样变态,只要按题意每一步对这个数不断维护更新就好。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#define LL long long
#define PI acos(-1.0)
#define maxn 100000 + 10
using namespace std;
int mod;
LL int sum[maxn<<2];
void pushup(int rt){//回溯更新(线段树是先对子节点更新,再对父节点进行更新)
sum[rt] = (sum[rt<<1] * sum[rt<<1|1]) % mod;
}
void build(int l,int r,int rt){//创建一棵线段树
int M=(l+r)>>1;
sum[rt] = 1;//全部初始化为1
if(l==r)//如果l==r的话直接返回
return ;
else{
build(l,M,rt<<1);//构造左子树
build(M+1,r,rt<<1|1);//构造右子树
pushup(rt);
}
}
void update(int p, long long v, int l, int r, int rt){
if(l == r){
sum[rt] = v % mod; //如果l==r的话直接更新并返回
return;
}
int M = (l + r) >> 1;
if(p <= M) update(p, v, l,M,rt<<1); //更新左子树
else update(p, v, M+1,r,rt<<1|1); //更新右子树
pushup(rt);
}
int main(){
int t;
scanf("%d",&t);
int cas=0;
while(t--){
int q;
scanf("%d%d",&q,&mod);
build(1,q,1);
printf("Case #%d:\n", ++cas);
for(int i=1;i<=q;++i){
int x,y;
scanf("%d%d",&x,&y);
if(x == 1)
update(i, y, 1, q, 1);
if(x == 2)
update(y, 1, 1, q, 1);
printf("%lld\n",sum[1]);
}
}
return 0;
}

1009
几何题。。。自己写的时候代码还错了好几次,居然是变量传错了,我也是醉了,看来智商是硬伤。

/*就是一个等腰三角形,底边中点也知道的情况下求min{∠MPB+∠APC,∠MPC+∠APB} 最大
首先我们画图画出来会发现其实这四个角相加刚好为360度,那么最大只能是180度,理由自己想。
既然是180度,而且又是等腰三角形,那么中线肯定满足我们的要求,所以该等腰三角形的中线长度
必然是答案的一部分。接下来就要像会不会有其他的点,而且而且当P点在B或C上时,满足条件。
这样我们其实可以预估其他的点所组成的图形肯定是一段圆弧。
那么这段圆弧与该等腰三角形的中线会相交与那个点呢?个人觉得肯定是特殊点,那么只有内心和外心了。
最后发现是内心,然后就是套公式咯。
详情可见http://blog.csdn.net/baileys0530/article/details/48753151*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<set>
#include<algorithm>
#define MOD 100000007
using namespace std;
struct Point
{
double x,y;
}A,B,C,M;//开结构体
double dis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int main(){
int t;
scanf("%d",&t);
int cases = 1;
while(t--){
scanf("%lf%lf%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y,&C.x,&C.y);
M.x = (B.x + C.x)/2.0,M.y = (B.y + C.y)/2.0;
double a1 = dis(B,C);
double a2 = dis(B,A);
double a3 = a1 / 2.0;
double h = dis(A,M);
double r = a1 * h /(a1 + 2 * a2);
double R = (a3 * a3 + r * r)/2.0/r;
double ans = asin(a3 / R) * R * 2;
ans += h;
printf("Case #%d: %.4lf\n",cases++,ans);
}
return 0;
}

1010
这道题的图片在高中物理里经常看见,其实题目也是物理题,某一段耗能,某一段储能然后问你能不能到达终点,而且他告诉你的是耗能的路段,而且最后到达终点的时候肯定是储能的路段,那这样我们只要倒推就好,只要他到最后一段储能路段的时候能量刚好消耗完,那么就符合题意,对输入的路段排个序倒推就可以得到结果,哦,那个第一段也肯定是储能的哦,减去就好。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cstring>
#include <climits>
#include <cmath>
#include <cctype>

using namespace std;

struct edge
{
int start,end1;
}road[110];

int cmp(const void* _a,const void* _b)
{
struct edge *a = (edge*)_a;
struct edge *b = (edge*)_b;
return a->end1 - b->end1;
}
int main()
{
int t,n,a,b,l;
int i,cas = 1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d%d",&n,&a,&b,&l);
for(i=0; i<n; i++)
{
scanf("%d%d",&road[i].start,&road[i].end1);
}
qsort(road,n,sizeof(road[0]),cmp);
int sum = 0;
sum += (road[n-1].end1 - road[n-1].start) * a;
for(i=n-2; i>=0; i--)
{
sum -= (road[i+1].start - road[i].end1) * b;
if(sum < 0)
sum = 0;
sum += (road[i].end1 - road[i].start) * a;
}
sum -= (road[0].start - 0) * b;
if(sum < 0)
sum = 0;
printf("Case #%d: %d\n",cas++,sum);
}
return 0;
}

1011
这道数论题把我搞死了,不过觉得这个网址挺有用的。
http://blog.csdn.net/queuelovestack/article/details/48754331
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: