今年又要打邀请赛了,前段时间做比赛都被虐的够呛,感觉不会再爱了。。。所以挂了下去年的成都邀请赛的题目。发现简单题还是能切上几道的,可是难题就无能为力了。。。阿门,还是水平差得远啊。。。(ps:近期感觉状态不佳,依靠了队友神勇的发挥。。。
Current Time: | 2014-05-15 08:43:24 | Contest Type: | Public |
Start Time: | 2014-05-14 15:10:00 | Contest Status: | Ended |
End Time: | 2014-05-14 20:10:00 | Manager: | ok_again |
Clone this contest
|
| ID | Origin | Title |
Problem A | ||||
Problem B | ||||
|
| Problem C | ||
Problem D | ||||
Problem E | ||||
|
| Problem F | ||
Problem G | ||||
Problem H | ||||
|
| Problem I | ||
Problem J | ||||
Problem K | ||||
Problem L |
A,一如既往的最签到的题目。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define eps 1e-8
#define PI acos(-1.0)
#define maxn 22000
#define INF 0x3f3f3f3f
#define E exp(double(1))
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
#ifdef __int64
typedef __int64 LL;
#else
typedef long long LL;
#endif
int main(){
int i,j,k,a,b;
int _,cas=1;
cin>>_;
while(_--){
cin>>a;
a/=10;
printf("Case #%d:\n",cas++);
puts("*------------*");
b=a;
a=10-a;
while(a--){
puts("|............|");
}
while(b--){
puts("|------------|");
}
puts("*------------*");
}
return 0;
}
B题找的是最长的距离最短,是一个下凹的图形,直接三分就可以。。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
const double eps=1e-8;
struct point{
double x,y;
point(double a=0,double b=0){
x=a,y=b;
}
point operator+(const point &a){
return point(a.x+x,a.y+y);
}
point operator*(const double &a){
return point(x*a,y*a);
}
void input(){
scanf("%lf%lf",&x,&y);
}
}p[500],vp[500],tmp[500];
int n;
double dist(point a,point b){
double x=a.x-b.x;
double y=a.y-b.y;
return sqrt(x*x+y*y);
}
double calc(double t){
for(int i=0;i<n;i++) tmp[i]=p[i]+vp[i]*t;
double res=-1;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++) res=max(res,dist(tmp[i],tmp[j]));
}
return res;
}
int main(){
int t;
scanf("%d",&t);
for(int cas=1;cas<=t;cas++){
scanf("%d",&n);
for(int i=0;i<n;i++){
p[i].input(),vp[i].input();
}
double l=0,r=1e20,mid,midmid;
double ans=0;
while(l+eps<r){
mid=(l+r)/2;
midmid=(mid+r)/2;
double mid_=calc(mid);
double midmid_=calc(midmid);
if(mid_<midmid_){
r=midmid;ans=mid_;
}
else l=mid;
}
printf("Case #%d: ",cas);
printf("%.2f %.2f\n",l,ans);
}
}
C题好像能够用LCA,保存6个值,各自是该区间的最长连续上升序列长度,左右端点连续上升序列长度,和分别得下降序列长度,便于查询时衔接用。。。比赛的时候想到了,可是没敲。。。所以这题代码就不给了。。。
D题好题线段树+dp+单调性,比赛的时候剩余时间不多了,没怎么想到正解。。。后来看了下大家用的是线段树,自己想了想,的确能够用线段树维护。。。当时就哭了。线段树中维护的是长度为L的那一段中,高度区间中dp[i]-h[i]的值(保存这个是由于,那个递推式,应该非常明显能看出来),然后就是怎么往树中加点和删点了,明显,同一高度的假设后面出现的val值比掐面出现的val值还要大的话,前面哪一个肯定是无用的,所以我们须要维护每一个高度整体单调递减,然后删除的时候推断一下当前删除点是否在树中就能够了。。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define eps 1e-7
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define E exp(double(1))
#define CLR(a, b) memset(a, b, sizeof(a))
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
using namespace std;
#ifdef __int64
typedef __int64 LL;
#else
typedef long long LL;
#endif
const int maxn = 222222;
LL MAX[maxn<<2];
int fir[maxn], nxt[maxn], h[maxn], pre[maxn], last[maxn];
void PushUP(int rt)
{
MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]);
}
void update(int p,LL sc,int l,int r,int rt)
{
if (l == r)
{
MAX[rt] = sc;
return ;
}
int m = (l + r) >> 1;
if (p <= m) update(p , sc , lson);
else update(p , sc , rson);
PushUP(rt);
}
LL query(int L,int R,int l,int r,int rt)
{
if (L <= l && r <= R)
{
return MAX[rt];
}
int m = (l + r) >> 1;
LL ret = -5;
if (L <= m) ret = max(ret , query(L , R , lson));
if (R > m) ret = max(ret , query(L , R , rson));
return ret;
}
LL dp[maxn];
void work(int cas)
{
int n, l;
scanf("%d%d", &n, &l);
for(int i = 1; i <= n; i ++)
{
scanf("%d", &h[i]);
}
CLR(MAX, -1);CLR(dp, -1);
CLR(pre, -1);
printf("Case #%d: ", cas);
for(int i = 1; i <= n; i ++)
{
LL tmp;
if(h[i] == 1) tmp = -1;
else tmp = query(1, h[i] - 1, 1, 100000, 1);
if(tmp == -1 && i > l)
{
goto ed;
}
if(tmp == -1) tmp = 0;
tmp += 1ll*h[i]*h[i] - h[i];
dp[i] = tmp;
int j;
for(j = pre[h[i]]; j != -1; j = last[j])
{
if(dp[j] > dp[i]) break;
}
if(j == -1)
{
pre[h[i]] = i;
fir[h[i]] = i;
last[i] = -1;
update(h[i], dp[i], 1, 100000, 1);
}
else
{
pre[h[i]] = i;
nxt[j] = i;
last[i] = j;
}
if(i <= l) continue;
ed:;
if(fir[h[i - l]] == i - l)
{
if(pre[h[i - l]] == fir[h[i - l]])
{
pre[h[i - l]] = -1;
update(h[i - l], -1, 1, 100000, 1);
}
else
{
fir[h[i - l]] = nxt[fir[h[i - l]]];
update(h[i - l], dp[fir[h[i - l]]], 1, 100000, 1);
}
}
}
if(dp[n] == -1) puts("No solution");
else printf("%I64d\n", dp[n] + h[n]);
}
int main()
{
int T, cas = 1;
scanf("%d", &T);
while(T --)
{
work(cas ++);
}
}
/*
555
5 1
24 5452 3542 452 14
*/
E题,这道题队友兴冲冲的就上去敲了,表示全然不知道题目。。。只是还是把代码附上吧。
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
const double eps=1e-8;
struct point{
double x,y;
point(double a=0,double b=0){
x=a,y=b;
}
void input(){
scanf("%lf%lf",&x,&y);
}
}p[4],now,ori;
double r;
double dist(point a,point b){
double x=a.x-b.x;
double y=a.y-b.y;
return sqrt(x*x+y*y);
}
point getpoint(point a,point b,point c){
double bx=b.x-a.x,by=b.y-a.y;
double cx=c.x-a.x,cy=c.y-a.y;
double d=2*(bx*cy-by*cx);
double x=(cy*(bx*bx+by*by)-by*(cx*cx+cy*cy))/d+a.x;
double y=(bx*(cx*cx+cy*cy)-cx*(bx*bx+by*by))/d+a.y;
return point(x,y);
}
void MiniOver(){
ori=p[0];r=0;
for(int i=1;i<3;i++){
if(dist(ori,p[i])+eps>r){
ori=p[i],r=0;
for(int j=0;j<i;j++)
if(dist(ori,p[j])+eps>r){
ori.x=(p[i].x+p[j].x)/2;
ori.y=(p[i].y+p[j].y)/2;
r=dist(ori,p[j]);
for(int k=0;k<j;k++)
if(dist(ori,p[k])+eps>r){
ori=getpoint(p[i],p[j],p[k]);
r=dist(ori,p[k]);
}
}
}
}
}
int main(){
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++){
for(int j=0;j<3;j++) p[j].input();
MiniOver();
now.input();
printf("Case #%d: ",i);
if(dist(now,ori)<=r) puts("Danger");
else puts("Safe");
}
}
G题是一道简单的数位dp。忘了0的情况。。。检查了n久,罪过啊。dp[i][j]表示长度为i位,余数为j有多少种数(包含前导零)。然后就显然了。。。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define eps 1e-7
#define PI acos(-1.0)
#define maxn 300
#define INF 0x3f3f3f3f
#define E exp(double(1))
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
#ifdef __int64
typedef __int64 LL;
#else
typedef long long LL;
#endif
LL dp[20][15];
void init()
{
CLR(dp, 0);
dp[0][0] = 1;
for(int i = 1; i < 20; i ++)
{
for(int j = 0; j < 10; j ++)
{
for(int k = 0; k < 10; k ++)
{
dp[i][(j + k) % 10] += dp[i - 1][j];
}
}
}
}
int c[25];
LL cal(LL a)
{
int len = 0;
while(a)
{
c[len ++] = a % 10;
a /= 10;
}
LL ret = 0;
int sum = 0;
for(int i = len - 1; i >= 0; i --)
{
if(i) for(int j = 1; j < 10; j ++)
{
ret += dp[i - 1][(10 - j)%10];
}
for(int j = 0; j < c[i]; j ++)
{
if(i == len - 1 && j == 0)
{
sum = (sum + 1) % 10;
continue;
}
ret += dp[i][(10 - sum) % 10];
sum = (sum + 1) % 10;
}
}
return ret;
}
int main()
{
int T, cas = 1;
init();
scanf("%d", &T);
while(T --)
{
LL a, b;
scanf("%I64d%I64d", &a, &b);
printf("Case #%d: ", cas ++);
LL ans = cal(b + 1) - cal(a);
if(a == 0) ans ++;
printf("%I64d\n", ans);
}
}
H题,贪心一下就好了。最左边上下两点可定要连线,然后分别捡短的线连就能够了。。。(正确性不可证,画了下图感觉挺对的。。)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define eps 1e-7
#define PI acos(-1.0)
#define maxn 100100
#define inf 0x3f3f3f3f
#define E exp(double(1))
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
#ifdef __int64
typedef __int64 LL;
#else
typedef long long LL;
#endif
int c[maxn], d[maxn], ca;
double len(int i, int j)
{
return sqrt(1.0*ca*ca + 1.0*(c[i] - d[j])*(c[i] - d[j]));
}
int main()
{
int T, cas = 1;
int n, m, a, b;
scanf("%d", &T);
while(T --)
{
scanf("%d%d", &a, &b);
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i ++)
{
scanf("%d", &c[i]);
}
for(int i = 0; i < m; i ++)
{
scanf("%d", &d[i]);
}
int y1, y2; ca = abs(a - b); double ans = 0.0;
ans += len(0, 0);
for(y1 = 0, y2 = 0; y1 < n && y2 < m;)
{
double tmp1 = 1e20, tmp2 = 1e20;
if(y1 == n - 1 && y2 == m - 1) break;
if(y1 < n - 1) tmp1 = len(y1+1, y2);
if(y2 < m - 1) tmp2 = len(y1, y2+1);
if(tmp1 < tmp2) ans += tmp1, y1 ++;
else ans += tmp2, y2 ++;
}
printf("Case #%d: %.2f\n", cas ++, ans);
}
}
J题想了n久才想到正解。。。本来想敲spfa的,队友说他先前敲的dij还在,就让他上去改了。。。大概就是我们须要把每一层都都当做一个节点,这种话第i层的点是能够更新第i+1层的全部点的,我们仅仅需把代表第i+1层的点更新了就能够了。。层节点代表的整层的信息。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define eps 1e-7
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define E exp(double(1))
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
#ifdef __int64
typedef __int64 LL;
#else
typedef long long LL;
#endif
#define maxn 201000
#define maxe 601000
struct Edge{
int from,to,dis,next;
}edge[maxe];
int head[maxn];
int n,m,c,cnt;
void add(int q,int h,int len){
edge[cnt].from=q;
edge[cnt].to=h;
edge[cnt].dis=len;
edge[cnt].next=head[q];
head[q]=cnt;
cnt++;
}
void init(){
cnt=0;
memset(head,-1,sizeof head);
}
int belong[maxn];
vector<int>v[maxn];
struct node{
int u,c;
node(int u,int c):u(u),c(c){};
node(){};
friend bool operator <(node a,node b){
return a.c>b.c;
}
}tmp;
int can[maxn];
int dis[maxn];
bool used[maxn];
priority_queue<node>q;
void dij(int s,int ttt){
int t,u,w;
while(!q.empty())q.pop();
memset(used,0,sizeof used);
memset(dis,inf,sizeof dis);
tmp=node(s,0);
dis[s]=0;
q.push(tmp);
if(belong[s]+1<=2*n && can[belong[s]+1]){
tmp=node(belong[s]+1,c);
dis[belong[s]+1]=c;
q.push(tmp);
}
if(belong[s]-1>n && can[belong[s]-1]){
tmp=node(belong[s]-1,c);
dis[belong[s]-1]=c;
q.push(tmp);
}
while(!q.empty()){
tmp=q.top();
q.pop();
t=tmp.u;
if(used[t])continue;
else used[t]=true;
for(int i=head[t];i!=-1;i=edge[i].next){
u=edge[i].to;
w=edge[i].dis;
if(used[u])continue;
if(dis[t]+w<dis[u]){
dis[u]=dis[t]+w;
q.push(node(u,dis[u]));
if(u<=n){
if(belong[u]<=n*2 && can[belong[u]+1] && dis[t]+w+c < dis[ belong[u]+1 ]){
dis[ belong[u]+1 ]=dis[t]+w+c;
q.push(node(belong[u]+1,dis[t]+w+c));
}
if(belong[u]-1>n && can[belong[u]-1] && dis[t]+w+c < dis[ belong[u]-1 ]){
dis[ belong[u]-1 ]=dis[t]+w+c;
q.push(node(belong[u]-1,dis[t]+w+c));
}
}
}
}
if(t>n){
if(t<=n*2 && can[t+1] && dis[t]+c < dis[ t+1 ]){
dis[ t+1 ]=dis[t]+c;
q.push(node(t+1,dis[t]+c));
}
if(t-1>n && can[t-1] && dis[t]+c < dis[ t-1 ]){
dis[ t-1 ]=dis[t]+c;
q.push(node(t-1,dis[t]+c));
}
}
}
}
inline int get_int(){
int ret=0;
char c;
while(!isdigit(c=getchar()));
do{
ret =(ret<<3)+(ret<<1)+c-'0';
}while(isdigit(c=getchar()));
return ret;
}
int main(){
int _,cas=1,q,h,cost;
cin>>_;
while(_--){
n=get_int(),m=get_int(),c=get_int();
init();
memset(can,0,sizeof can);
for(int i=1;i<=n;i++){
belong[i]=get_int();
belong[i]+=n;
can[belong[i]]=1;
}
for(int i=0;i<m;i++){
q=get_int(),h=get_int(),cost=get_int();
add(belong[q],h,cost);
add(belong[h],q,cost);
add(q,h,cost);
add(h,q,cost);
}
dij(1,n);
printf("Case #%d: ",cas++);
int ans=min(dis[belong[n]],dis[n]);
if(ans==inf){
puts("-1");
}else{
printf("%d\n",ans);
}
}
return 0;
}
K题是一道计数题?没看题。。。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define eps 1e-8
#define PI acos(-1.0)
#define maxn 2200000
#define INF 0x3f3f3f3f
#define E exp(double(1))
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
#ifdef __int64
typedef __int64 LL;
#else
typedef long long LL;
#endif
char s[maxn];
int c1[11];
int cp1[11];
int cp2[11];
int c2[11];
int x1,x2;
int cnt[11];
int ctt[11];
int gethead(){
for(int i=9;i>=0;i--){
for(int j=0;j<=9;j++){
int tt = (i-j);
if(tt<0)tt+=10;
if(j==0||tt==0)continue;
if(c1[j]&&c2[tt]){
return i;
}
}
}
}
void getnext(){
for(int sum=9;sum>=0;sum--){
for(int a=0;a<=9;a++){
int b = (sum-a);
if(b<0)b+=10;
int cc = min(c1[a],c2[b]);
c1[a]-=cc;
c2[b]-=cc;
cnt[sum]+=cc;
}
}
bool ok;
for(int i=9;i>=0;i--){
if(cnt[i]==ctt[i])continue;
if(cnt[i]<ctt[i])ok=false;
else ok=true;
break;
}
if(ok){
for(int i=0;i<=9;i++){
ctt[i]=cnt[i];
}
}
}
int main(){
int _,cas=1;
cin>>_;
while(_--){
memset(c1,0,sizeof c1);
memset(c2,0,sizeof c2);
memset(cnt,0,sizeof cnt);
memset(ctt,0,sizeof ctt);
scanf("%s",s);
for(int i=0;s[i];i++)c1[s[i]-'0']++;
scanf("%s",s);
for(int i=0;s[i];i++)c2[s[i]-'0']++;
int h = gethead();
for(int i=0;i<=9;i++){
cp1[i]=c1[i];
cp2[i]=c2[i];
}
for(int i=0;i<=9;i++){
for(int j=0;j<=9;j++){
c1[j]=cp1[j];
c2[j]=cp2[j];
}
int tt = (h-i);
if(tt<0)tt+=10;
if(i==0||tt==0)continue;
if(c1[i]&&c2[tt]){
c1[i]--;
c2[tt]--;
memset(cnt,0,sizeof cnt);
getnext();
}
}
bool ok=false;
if(h!=0)ok=true;
printf("Case #%d: ",cas++);
if(h!=0)printf("%d",h);
for(int i=9;i>=1;i--){
while(ctt[i]--){
printf("%d",i);
ok=true;
}
}
if(ok){
while(ctt[0]--){
printf("%d",0);
}
}else{
printf("0");
}
puts("");
}
return 0;
}
L题,第二签到题。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define eps 1e-8
#define PI acos(-1.0)
#define maxn 220000
#define INF 0x3f3f3f3f
#define E exp(double(1))
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
#ifdef __int64
typedef __int64 LL;
#else
typedef long long LL;
#endif
int s[maxn];
int main(){
int i,j,k,n,b;
int _,cas=1;
cin>>_;
while(_--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&s[i]);
}
b=-1;
for(int i=2;i<=n;i++){
if(s[i]-s[i-1]!=1){
b=i;
}
if(~b)break;
}
if(b==-1)b=1;
printf("Case #%d: %d\n",cas++,b);
}
return 0;
}