您的位置:首页 > 其它

Cf 103 div.2

2012-01-19 21:45 197 查看
A题

It's clear that the leftmost soldier with the maximum height should be the first and the rightmost soldier with the minimum height should be the
last. Thus we will minimize the number of swaps. And the answer is number of leftmost soldier with the maximum height - 1 + n - number
of rightmost soldier with the minimum height. And if the leftmost soldier with the maximum height is more right then the rightmost soldier with the minimum height we should subtract one from the answer.

B题,昨晚题目没看懂,先做的C题,后来胡乱弄个代码,提交Pretest,最后是被测挂了。

题意: 一个x-y轴,-1000到1000,有n<=1000个圆,有一个矩形,问矩形的边界上的点有多少个没有被圆覆盖(点在圆边界上也算覆盖),保证所有的数字都是整数,即半径r是整数,点都是整点。

注意英文里的perimeter除了表示周长的意思,还可以表示边界,这导致我读题很混乱。

昨天的想法是,每个圆循环判定所有的点,时间复杂度O( n* num of point ),不知为何昨晚估算有4000个点,结果测挂了,今天重写到8000个点就ac了,我的代码还是贴下,里面有eps,注意了。 还贴上一个人的代码,值得借鉴。

针对下面另一个人的代码,我又在帖子里看到一句话:

Useful hint:

For comparing distances you dont need to get square root, you can compare squares => no doubles + no sqrt.

hypot() is slow

觉得很受用,所以以后得注意了。。。

我的:

/*Jan 19, 2012 5:33:54 PM yimao B-Meeting GNU C++ Accepted 220ms 1400KB*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
#define MM(a,b) memset(a,b,sizeof(a));
typedef unsigned long long u64;
typedef long long lld;
#define maxn
#define eps (1e-6)
int x[8050],y[8050];
bool f[8050];
int rx,ry,r;

bool judge(int i){
if( ( sqrt( 0.0+ (rx-x[i])*(rx-x[i]) + (ry-y[i])*(ry-y[i]) ) - r )< eps ) return 1;
else return 0;
}

int main()
{
//freopen("B.txt","r",stdin);
int n,i,xa,xb,ya,yb;
while(cin>>xa>>ya>>xb>>yb){
int N=0;
MM(f,0);
int st_x= min(xa,xb), ed_x= max(xa,xb);
int st_y= min(ya,yb), ed_y= max(ya,yb);
for(i=st_x;i<=ed_x;++i)
x[++N]= i, y
= st_y;
for(i=st_x;i<=ed_x;++i)
x[++N]= i, y
= ed_y;
for(i=st_y+1;i<ed_y;++i)
x[++N]= st_x, y
= i;
for(i=st_y+1;i<ed_y;++i)
x[++N]= ed_x, y
= i;
//printf("N=%d\n",N);

cin>>n;
while(n--){
scanf("%d%d%d",&rx,&ry,&r);
for(i=1;i<=N;++i)
if( !f[i] ){
if( judge(i)==1 ){
f[i]=1;
}
}
}
int ans=0;
for(i=1;i<=N;++i)
if( !f[i] )
ans++;
printf("%d\n",ans);
}
}


一个大牛的:

#include <iostream>
#include <cstdio>
#include <sstream>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <map>
#include <set>
#include <bitset>
#include <queue>
#define zero(a) (abb(a)<eps)
#define lowbit(a) ((a)&(-(a)))
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abb(a) ((a)>0?(a):(-(a)))
#define cj(x1,y1,x2,y2) ((x1)*(y2)-(x2)*(y2))
#define dj(x1,y1,x2,y2) ((x1)*(y1)+(y1)*(y2))
#define dis(x1,y1,x2,y2) (((x2)-(x1))*((x2)-(x1))+((y2)-(y1))*((y2)-(y1)))
const double eps = 1e-9;
const int oo = 1000000000;
const double E = 2.7182818284590452353602874713527;
const double pi = 3.1415926535897932384626433832795;
using namespace std;

int x[1001],y[1001],r[1001];
int n;

bool check(int px,int py)
{
for (int i=1;i<=n;i++)
if (dis(px,py,x[i],y[i])<=r[i]*r[i])
return 0;
return 1;
}

int main()
{
int x1,y1,x2,y2,s=0;
cin>>x1>>y1>>x2>>y2>>n;
for (int i=1;i<=n;i++)
cin>>x[i]>>y[i]>>r[i];
for (int i=min(x1,x2);i<=max(x1,x2);i++)
s+=check(i,y1)+check(i,y2);
for (int i=min(y1,y2)+1;i<max(y1,y2);i++)
s+=check(x1,i)+check(x2,i);
cout<<s<<endl;
return 0;
}


C题,

I wanted to solve problem C with the idea most contestants did. To have an array of size 26 for S & P and then processing it. My big mistake was that I taught
it would get TLE. Can someone explain me the time of this idea???

Reply:

The time is O(|S| * Aplhabet). Because you take |T| - |S| strings and check them with time
O(Alphabet).

So time is O((|T| - |S|) * Aplhabet) = O(|S| * Alphabet).

You can get TL if you work with strings and get new string using substr, delete or something other, that works O(|S|).

然后在哦我看完blog后才知道,我的代码中一个对 ? 的计数是完全多余的,真的是多余的,见下面的标程分析:

Let's count number of each letter in the second string and save it, for example, in array a[1..26].
For the first strings' prefix of lengthn,
where n is the length of second string,
(it's the first substring) we count number of each letter in array b[1..26].
We don't count characters ``\texttt{?}''. If there are b[i] ≤ a[i] for
all i, then it's good substring. Then go
to the second substring: subtract from the array b the
first character: b[s[1] - 'a' + 1] –  and
add n + 1 character: b[s[n + 1] - 'a' + 1] +  + .
If some of these characters is ``\texttt{?}'' then we shouldn't do for it the subtraction or addition. Then repeat the showed check and go to the next substring. Let's repeat this procedure for all substrings of length n.

D题

给n个点,m条赋权边,n<=10^5, m= min( 10^5, n*(n+1)/2 );,一个顶点s,一个距离值L,问距离顶点s的距离为L的位置的个数,包含顶点和边上的某点。

首先,Dijkstra + set 求每个点到s的最短路。

然后统计cnt:

1、对于每个点,如果dis[ point ] == L, cnt++;

2、对于每条边,如果:

dis[u]<L && dis[u]+w>L && dis[u]+w-L+dis[v]>L,则cnt ++;

dis[v]<L && dis[v]+w>L && dis[v]+w-L+dis[u]>L,则cnt++;

dis[u]<L && dis[v]<L && dis[v]+dis[u]+w == L+L,则cnt++;

/*Jan22, 2012 7:56:32 PM yimao D-Missile Silos GNU C++ Accepted 170ms	10200KB*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
#define MM(a,b) memset(a,b,sizeof(a));
typedef unsigned long long u64;
typedef long long lld;
#define maxn 200050
const int maxint= 2000000000;

int top;
struct Edge{
int u,v,w;
Edge *next;
}*adj[maxn], edge[maxn];
int ux[maxn],vx[maxn],wx[maxn];
int n,m,s,L;

void Add_edge(int u,int v,int w){
Edge *ptr= &edge[++top];
ptr->u= u, ptr->v= v, ptr->w= w;
ptr->next= adj[u];
adj[u]= ptr;
}

// Dijkstra + set, can count |V|<10^5,|E|<10^5;
int dis[maxn];
bool use[maxn];
struct cmp{
bool operator()(int i,int j)const{
return dis[i]<dis[j] || (dis[i]==dis[j]&&i<j);
}
};
set<int,cmp>Q;
void Dijkstra(){
for(int i=1;i<=n;++i) dis[i]= maxint, use[i]=0;
dis[s]=0;
if( !Q.empty() ) Q.clear();
Q.insert( s );
while( !Q.empty() ){
int u= *Q.begin();
use[u]= 1;
Q.erase( u );
for( Edge *p= adj[u];p;p=p->next ){
int v= p->v;
if( use[v]==0 && dis[v]> dis[u]+ p->w ){
Q.erase( v );
dis[v]= dis[u]+ p->w; //after update v,can it be insert;
Q.insert( v );
}
}
}
}

int solve(){
int i,cnt=0;
for(i=1;i<=n;++i) if( dis[i]==L ) cnt++;
for(i=1;i<=m;++i){
int u= ux[i], v= vx[i], w= wx[i];
if( dis[u]<L && dis[u]+w>L && dis[u]+w-L+dis[v]>L )
cnt++;
if( dis[v]<L && dis[v]+w>L && dis[v]+w-L+dis[u]>L )
cnt++;
if( dis[u]<L && dis[v]<L && dis[v]+dis[u]+w == L+L )
cnt++;
}
return cnt;
}

int main()
{
//freopen("D.txt","r",stdin);
int i,j;
while(cin>>n>>m>>s){
top=0;
MM( adj, 0 );
for(i=1;i<=m;++i){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
ux[i]=u, vx[i]=v, wx[i]=w;
Add_edge( u, v, w );
Add_edge( v, u, w );
}
/*for(i=1;i<=n;++i){
for(Edge *p= adj[i];p;p= p->next)
printf("%d %d %d\n",i,p->v,p->w);
puts("");
}*/
cin>>L;
Dijkstra();
/*for(i=1;i<=n;++i)
printf("%d  %d\n",i,dis[i]); puts("");*/
int ans= solve();
cout<<ans<<endl;
}
}


E题

我是赛后ac的。。。贪心+优先队列

题意:见题目

分析:首先题目规定必须是走最短路到达对角线,那么可以确定对于任意对角线上的格子,一定是其右下角的sportmen到达该格。所有sportmen按y排降序,按x排升序,然后我们对最后一行,把所有在最后一行的sportman加入优先队列(优先队列以x为第一关键字排升序),队首元素即是我们需要的,然后对倒数第二行,把所有倒数第二行的sportman加入优先队列,取队首元素,看队首元素是否在对角线点的右下方,在则表示取该点,否则不取,pop之,再取top。。。。。贪心下去就是了,

/*Jan24,2012 12:47:21 PM yimao E-Competition GNU C++ Accepted 170ms 5300KB*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define MM(a,b) memset(a,b,sizeof(a));
typedef unsigned long long u64;
typedef long long lld;
#define maxn 100050

int n,m;
struct Node{
int x,y,index;
bool operator<(Node a)const{
return y>a.y || (y==a.y&&x<a.x);
}
}node[maxn];
int c[maxn];

struct Temp_Node{
int x,y,index;
bool operator<(Temp_Node a)const{
return x>a.x|| (x==a.x&&y>a.y); //////be careful for priority_queue;
}
};
priority_queue<Temp_Node>Q;

int main()
{
//freopen("E.txt","r",stdin);
int i,j;
while(cin>>n>>m){
for(i=1;i<=m;++i){
scanf("%d%d",&node[i].x, &node[i].y);
node[i].index= i;
}
sort( node+1, node+1+m );
while( !Q.empty() ) Q.pop();
int ans=0, index=1;

for(i=1;i<=n;++i){
for(;index<=m;++index){
if( node[index].y>= (n+1-i) ){
Temp_Node tmp;
tmp.x= node[index].x, tmp.y= node[index].y;
tmp.index= node[index].index;
Q.push( tmp );
}
else break;
}
while( !Q.empty() ){
Temp_Node tmp= Q.top();
Q.pop();
//printf("oo i=%d %d   %d\n", i,tmp.x, tmp.index);
if( tmp.x<i )
continue;
c[ ++ans ]= tmp.index;
break;
}
}
printf("%d\n",ans);
for(i=1;i<=ans;++i){
printf("%d",c[i]);
if( i==ans ) puts("");
else printf(" ");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: