hut_csust 训练赛第三场 解题报告
题目链接: www.acmore.net
Problem A
遍历数组a, 对于每一个元素 a[i], 统计区间 ( a[i], a[i]+d ] 有X个点,则符合条件的为 C(2,X)
累加就可以了
解题代码
View Code
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
const int N = 1e5+10;
const int M = 1e6;
map< LL, int > Mp;
int n, C[M+10], size;
LL a[N], d, b[M];
void update( int x )
{
for(; x <= M; x += (x&(-x)) )
C[x] += 1;
}
int read( int x )
{
int res = 0;
for( ; x >= 1; x -= (x&(-x)) )
res += C[x];
return res;
}
int main()
{
while( scanf("%d%lld", &n, &d) != EOF)
{
Mp.clear();
size = 0;
for(int i = 0; i < n; i++ )
{
scanf("%lld", &a[i]);
b[size++] = a[i];
b[size++] = a[i]+d;
}
sort( b, b+size );
size = unique( b, b+size) - b;
int tmp = 1;
for(int i = 0; i < size; i++)
Mp[ b[i] ] = tmp++;
memset( C, 0, sizeof(C));
for(int i = 0; i < n; i++)
update( Mp[ a[i] ] );
LL ans = 0; for(int i = 0; i < n; i++)
{
int k = read( Mp[ a[i]+d ] ) - (i+1);
if( k > 1 )
ans += 1LL*k*(k-1)/2;
}
printf("%lld\n", ans );
}
return 0;
}
Problem B
字符串处理,取最长的,当有多个,则字典序最大的是结果
解题代码
View Code
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
char str[110][110];
vector< string > S;
int main()
{
int n;
while( scanf("%d", &n) != EOF )
{
int L = 0;
for(int i = 0; i < n; i++)
{
scanf("%s", str[i] );
if( strlen( str[i] ) > L )
L = strlen(str[i]);
}
S.clear();
for(int i = 0; i < n; i++)
if( strlen(str[i]) == L )
S.push_back( str[i] );
sort( S.begin(), S.end() );
printf("%s\n", (S[ S.size()-1 ]).c_str() );
}
return 0;
}
Problem C
递推, F(N) = F(N-1)+ F(N-2)
解题代码
View Code
#include<stdio.h>
typedef long long LL;
LL f[55] = {1,1,2};
int main()
{
for(int i = 3; i <= 50; i++)
f[i] = f[i-1]+f[i-2];
int a, b, T;
scanf("%d", &T);
while( T-- && scanf("%d%d", &a,&b) )
printf("%lld\n", f[b-a] );
return 0;
}
Problem D
枚举长度O(N),之后枚举左边界O(N), 使用差值取模O( LogN ) 判定, 总时间复杂度为 O( N*N*LogN)
解题代码
View Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef unsigned long long LL;
char s1[1010];
int n;
LL A[1010],B[1010], C[2][2020], T[1010];
void add(int key, int x, LL val )
{
for(; x <= 1000; x+=(x&(-x)))
C[key][x] += val;
}
LL read(int key, int x)
{
LL res = 0;
for(; x >= 1; x -= (x&(-x)) )
res += C[key][x];
return res;
}
void init()
{
A[0] = B[0] = 0;
for(int i = 1; i <= n; i++)
{
A[i] = (s1[i]-'a'+1)*T[i-1];
B[i] = (s1[n+1-i]-'a'+1)*T[i-1];
}
memset( C, 0, sizeof(C));
for(int i = 1; i <= n; i++)
{
add( 0, i, A[i] );
add( 1, i, B[i] );
}
}
int find( int len )
{
for(int i = 1; i+len-1 <= n; i++ )
{
int a = i, b = i+len-1;
int c = (n+1)-b, d = (n+1)-a;
LL sa = read(0,b)-read(0,a-1);
LL sb = read(1,d)-read(1,c-1);
sa *= T[c-1]; sb *= T[a-1];
if( sa == sb ) return i;
}
return -1;
}
int main()
{
T[0] = 1;
for(int i = 1; i <= 1010; i++)
T[i] = T[i-1]*27;
while( scanf("%s", s1+1) != EOF)
{
n = strlen(s1+1);
init();
for(int m = n; m >= 1; m-- )
{
int s = find(m);
if( s != -1 )
{
for(int i = s; i < s+m; i++)
printf("%c", s1[i]); puts("");
break;
}
}
}
return 0;
}
Problem E
按分数排序
解题代码
View Code
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
using namespace std;
const int N = 5150;
struct node
{
char name[30];
double score;
bool operator < ( node tmp ) const
{
return score > tmp.score;
}
void read( )
{
scanf("%s %lf", name, &score );
}
}stu[N];
int n, r;
char str[30];
int main()
{
while( scanf("%d", &n) !=EOF)
{
for(int i = 0; i < n; i++)
stu[i].read();
sort( stu, stu+n );
scanf("%d", &r);
while( r-- )
{
scanf("%s", str );
for(int i = 0; i < n; i++)
if( strcmp( stu[i].name, str ) == 0 )
{
printf("%d\n", i+1);
break;
}
}
}
return 0;
}
Problem F
BFS广搜即可,因为每个点至多走一次,也才10*10. 注意起点也算1步
解题代码
View Code
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<queue>
using namespace std;
char map[15][15];
int n, m, s;
int vis[15][15];
struct node
{
int x, y;
int step;
}info,nxt;
bool legal(int x, int y)
{
if( x >= 1 && x <= n && y >= 1 && y <= m )
return true;
return false;
}
void getdir( int x1, int y1, int &x, int &y )
{
switch( map[x1][y1] )
{
case 'W':
x = x1;
y = y1-1;
break;
case 'E':
x = x1;
y = y1+1;
break;
case 'N':
x = x1-1;
y = y1;
break;
case 'S':
x = x1+1;
y = y1;
break;
}
}
queue<node> Q;
void solve()
{
memset( vis , 0, sizeof(vis) );
while( !Q.empty() ) Q.pop();
info.x = 1; info.y = s;
info.step = 1;
Q.push(info);
vis[info.x][info.y] = 1;
while( !Q.empty() )
{
info = Q.front(); Q.pop();
int x, y;
getdir( info.x,info.y,x,y);
if( !legal(x,y) )
{
printf("%d step(s) to exit\n",info.step);
return;
}
else if( vis[x][y] )
{
printf("%d step(s) before a loop of %d step(s)\n", vis[x][y]-1, info.step-vis[x][y]+1);
return;
}
else
{
vis[x][y] = info.step+1;
nxt.step = info.step+1;
nxt.x = x; nxt.y = y;
Q.push(nxt);
}
}
}
int main()
{
while( scanf("%d%d%d", &n, &m, &s) != EOF)
{
if( !(n+m+s) ) break;
for(int i = 1; i <= n; i++)
scanf("%s", map[i]+1);
solve();
}
return 0;
}
Problem G
位运算,异或, 当都为1时才为1,否则为0
初始令X = 0, 与所有数异或,那么相同的数,偶数个后都会为0,剩下的就是奇数个的值
注意,后台数据貌似没有 N=0,所以结束条件为 EOF,否则会TLE
解题代码
View Code
#include<stdio.h> int main() { int n; while( scanf("%d", &n) != EOF ) { if( n == 0 ) break; int a, x = 0; for(int i = 1; i <= n; i++) { scanf("%d", &a); x ^= a; } printf("%d\n", x); } return 0; }
Problem H
11年网络赛立体空间的简单版.
枚举两个水果成直线,然后扫其他水果. 利用叉积判定是否在直线上.
注意 坐标为 double类型. WA在了这上面
解题代码
View Code
#include<stdio.h> #define max(x,y) (x)>(y)?(x):(y) #define min(x,y) (x)<(y)?(x):(y) const int inf=0x7fffffff; typedef long long LL; struct node // Fruit { double x,y; void read( ) { scanf("%lf%lf", &x,&y); } }Q[1010]; const double esp = 1e-8; int sign(double x ) { return (x<-esp)? -1 : (x>esp); } bool judge( double x1,double y1,double x2,double y2,double x,double y ) { if( ( sign( ( x1-x )*( y2-y ) - ( x2-x )*( y1-y ) )) == 0 ) return true; return false; } int n; int main() { int T; scanf("%d", &T); for(int Case = 1; Case <= T; Case++ ) { scanf("%d", &n); int ans = 1; for(int i = 0; i < n; i++) Q[i].read(); for(int i = 0; i < n; i++) for(int j = i+1; j < n; j++) { int cnt = 2; for(int k = j+1; k < n; k++) { if( judge( Q[i].x, Q[i].y, Q[j].x, Q[j].y, Q[k].x, Q[k].y ) ) cnt++; } ans = max( ans, cnt ); } printf("Case %d: %d\n",Case, ans ); } return 0; }
Problem I
按要求使用栈模拟即可.
解题代码
View Code
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<algorithm> #include<queue> #include<stack> #include<iostream> using namespace std; stack<string> s1, s2; string op, web, cur; int main() { int Case = 1; while( cin>>op ) { while( !s1.empty() ) s1.pop(); while( !s2.empty() ) s2.pop(); printf("Case %d:\n", Case++); cur = "http://www.acmore.net/"; cout << cur << endl; while( cin>>op ) { // cout << "op = " << op << endl; if( op == "end" ) { cout << "end" << endl; break; } else if( op == "visit" ) { cin >> web; // cout << "web = " << web << endl; while( !s2.empty() ) s2.pop(); s1.push( cur ); cur = web; cout << cur << endl; } else if( op == "back" ) { if( !s1.empty() ) { s2.push( cur ); cur = s1.top(); s1.pop(); cout << cur << endl; } else cout << "This is the first page" << endl; } else if( op == "forward" ) { if( !s2.empty() ) { s1.push( cur ); cur = s2.top(); s2.pop(); cout << cur << endl; } else cout << "This is the last page" << endl; } } } return 0; }
Problem J
模拟题.....
解题代码
View Code
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> using namespace std; int num[10]; char G[1000][1000]; int main() { int N, M; while (scanf("%d %d", &N, &M), N|M) { memset(num, 0, sizeof (num)); for (int i = 0; i <= N*5; ++i) { scanf("%s", G[i]); } for (int i = 0; i < N; ++i) { for (int j = 0; j < M; ++j) { int cnt = 0; int l = i*5+1, r = i*5+4, u = j*5+1, d = j*5+4; for (int p = l; p <= r; ++p) { for (int q = u; q <= d; ++q) { if (G[p][q] == '*') { ++cnt; } } } num[cnt/4]++; } } for (int i = 0; i < 5; ++i) { printf(i == 0 ? "%d" : " %d", num[i]); } puts(""); } return 0; }

View Code
浙公网安备 33010602011771号