您的位置:首页 > 其它

Codeforces Round #365 (Div. 2) 题解

2016-08-05 15:26 381 查看
第一题Mishka and Game

题目大意,2个人玩骰子,问谁赢的次数多。

我吃了泡面问队友,第一题什么意思。队友说,“他们玩若干轮,看谁总点数大”。

然后,我猜全场只有我们俩WA了……

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstring>
#include <vector>
#include <map>
#include <string>
using namespace std;

typedef long long LL;
const int maxn = 100000 + 100;
int n;

LL powMod( LL a , LL b , LL p )//a^b % p
{
LL r = 1 ;
a %= p ;
while( b )
{
if( b&1 ) r = r*a%p ;
b >>= 1 ;
a = a*a%p ;
}
return r ;
}

int main()
{
cin >> n;
int a=0,b=0;
while (n--)
{
int x,y;
cin >>x>>y;
if (x>y)++a;
if (y>x)++b;
}
if (a==b) cout<<"Friendship is magic!^^"<<endl;
if (a>b) cout<<"Mishka"<<endl;
if (a<b) cout<<"Chris"<<endl;
return 0;
}


第二题Mishka and trip
题目大意,有n个点,i和-1的点连接,1和n连接。是一个环。

有K个牛X城市,这些城市和任意城市都连接。

两个城市的距离为两个城市的权重乘积,问所有道路的权重和。

(两个城市最多只有一条路连接)

先求出所有【城市的】权重和为sum,和所有相邻城市【道路】的权重和为ans。

然后题目给出的牛X城市的编号,已经按顺序给好了,所以只要从第一个城市开始,a[i]假设为第i个牛B城市的编号,f[i]假设为第i个城市的权重

那么f[a[i]] * (sum-f[a[[i]]) j就是这个城市到所有点的权重,然后去掉和相邻点的边权即可。

注意特判连续2个都是牛X城市的情况,和首位是牛X城市的情况即可。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstring>
#include <vector>
#include <map>
#include <string>
using namespace std;

typedef long long LL;
const int maxn = 100000 + 100;
int n, m;

LL powMod( LL a , LL b , LL p )//a^b % p
{
LL r = 1 ;
a %= p ;
while( b )
{
if( b&1 ) r = r*a%p ;
b >>= 1 ;
a = a*a%p ;
}
return r ;
}

LL f[maxn], sum=0, a[maxn];
LL ans=0;

void init()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <=n;++i) scanf("%I64d", &f[i]);
for (int i = 1; i <= m; ++ i) scanf("%I64d", &a[i]);

for (int i = 1; i <=n; ++ i) sum += f[i];
LL sum2=0;
for (int i = 1;i<=m;++i) sum2+= f[a[i]];
f[0] = f
;
f[n + 1] = f[1];
a[0]=-100;

for (int i = 1; i <= n; ++ i) ans += f[i] * f[i - 1];
for (int i = 1; i <= m; ++ i)
{
LL tmp1 = f[a[i]] * (sum-f[a[i]]);
LL tmp2 = f[a[i]] * (f[a[i] - 1] + f[a[i] + 1]);
sum -= f[a[i]];
//cout<<tmp1<<" "<<tmp2<<" "<<ans << endl;
if (a[i] == a[i - 1] + 1) ans += f[a[i]] * f[a[i] - 1];
ans += tmp1 - tmp2;
}
if (a[m] == n && a[1] == 1) ans += f
*f[1];

cout << ans << endl;

}

int main()
{
init();

return 0;
}



C题Chris and Road
题目大意,给一个凸包,这个凸包从右边往左边动,一个人要过马路。问,不被凸包撞到,过马路的最短时间。 凸包的速度,和人的速度都给出了。人只能走直线(横穿马路)。

假设凸包上一个点P,到达X=0的直线的时间是T时间,而人到达同一个点的时间为Q时间。如果对于所有的Q,都满足Q<T,那么行人是可以直接穿过马路的。

否则,可以选择一个最大值,答案就是max(T + 行人从这个点直接穿越马路的时间)。

正确性。。有点显然,没去证明,在纸上画一画,就懂了……很显然的啊

#include <iostream>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstring>
#include <vector>
#include <map>
#include <string>
using namespace std;

typedef long long LL;
const int maxn = 1000000 + 100;

int main()
{
int n;
double w,u,v;
scanf("%d%lf%lf%lf", &n, &w, &u, &v);
int flag=1;
double ans =w/v;
for (int i = 1; i <=n;++i)
{
double x,y;
scanf("%lf%lf", &x, &y);
//车来的时间
if (y/v>x/u) flag=0;
ans=max(ans, x/u + (w-y)/v);
}
if (!flag) printf("%.6lf\n", ans);
else printf("%.6lf\n",w/v);
return 0;
}



D题Mishka and Interesting sum
题目大意:

给一大堆数字,问[L,R]区间,数字出现偶数次的数字,全部XOR起来的结果。

比如区间内数字有【1,2,3,3,2,1,1】

1 出现3次

2出现2次

3出现2次

结果就是2 xor 3,这两个数字出线的次数是偶数次。

显然,区间【所有数字,可以重复出现】直接xor起来的结果,相当于xor了出现奇数次的数字。

如果区间所有数字,每个【数字只选一个】全部xor起来的结果,再xor上奇数次的结果,就是答案了。

第一问简单解决。第二问,可以离线,用树状数组维护一下就行了

这题莫队TLE……我读入都优化了……还是T14~ 一看数据1e6哇哈哈卡了莫队。

听说主席树炸内存……真可怕

先上T14的莫队。

#include <iostream>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstring>
#include <vector>
#include <map>
#include <string>
using namespace std;

typedef long long LL;
const int maxn = 1000000 + 100;

const int MAXN = 1000000 + 100;
const int MAXM = 1000000 + 100;
struct Query
{
int L,R,id;
}node[MAXM];

int a[MAXN];
int output[maxn];
int n,m,unit;
bool cmp(Query a,Query b)
{
if(a.L/unit != b.L/unit)return a.L/unit < b.L/unit;
else return a.R < b.R;
}

map<int, int>haxi[1000000];
const int mod = 999983;
map<int, int>::iterator it;
int ret, t;

inline int insert(int k)
{
t = k % mod;
if ((it = haxi[t].find(k)) == haxi[t].end())
{
ret = haxi[t][k] = 1;
}
else ret = ++(it -> second);
return ret;
}

inline int dec(int k)
{
return --haxi[k % mod][k];
}

inline int add(int k)
{
return ++haxi[k % mod][k];
}

map<LL, LL>mp;

namespace IStream {
const int L = 1 << 15;
char buffer[L], *S, *T;
inline char get_char() {
if (S == T) {
T = (S = buffer) + fread(buffer, 1, L, stdin);
if (S == T) exit(0);//return EOF;
}
return *S++;
}
inline int get_int(int& tvalue) {//只能读正整数,返回读入的数,读入失败返回0
char c;
int re = 0;
for (c = get_char(); c<'0' || c>'9'; c = get_char());
while (c >= '0' && c <= '9')
re=(re<<1)+(re<<3)+(c-'0'), c=get_char();
return tvalue = re;
}
inline int get_int2(int& tvalue) {//含有负数的整型读入, 成功返回1 失败返回EOF
char c;
int re = 0, sgn = 1;
for (c = get_char(); c != EOF && c != '-' && (c<'0' || c>'9'); c = get_char());
if (c == EOF) return EOF;
if (c == '-') { sgn = -1; c = get_char(); }
while (c >= '0' && c <= '9')
re=(re<<1)+(re<<3)+(c-'0'), c=get_char();
tvalue = sgn * re;
return 1;
}
}
using IStream::get_int2;

void work()
{
mp.clear();
int L = 1;
int R = 0;
int now=0;
for(int i = 1;i <= m;i++)
{
while(R < node[i].R)
{
R++;
if (insert(a[R]) >= 2) now ^= a[R];
}
while(R > node[i].R)
{
if (dec(a[R])) now ^= a[R];
-- R;
}
while(L < node[i].L)
{
if (dec(a[L])) now ^= a[L];
L++;
}
while(L > node[i].L)
{
L--;
if ((add(a[L]))>=2) now ^= a[L];
}
output[node[i].id] = now;
}
}

int main()
{
get_int2(n);
for (int i = 1; i <= n; ++ i) get_int2(a[i]);//scanf("%d", &a[i]);
get_int2(m);
for (int i =1; i<=m; ++ i)
{
node[i].id = i;
get_int2(node[i].L);
get_int2(node[i].R);
//scanf("%d%d", &node[i].L, &node[i].R);
}
unit = (int)sqrt(n);
sort(node + 1, node + 1 + m, cmp);
work();
for (int i = 1; i <=m;++i) printf("%d\n", output[i]);
return 0;
}



然后才是AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstring>
#include <vector>
#include <map>
#include <string>
using namespace std;

typedef long long LL;
const int maxn = 1000000 + 100;
int n;

int t[maxn];
int a[maxn], sum[maxn];
int q[maxn];
int ans[maxn];
map<int,int>mp;

struct query
{
int l, id;
};
vector<query>g[maxn];

int ask(int l, int r)
{
int ret=0;
for (--l;l;l-=(l&(-l))) ret^=t[l];
//cout<<ret<<endl;
for (;r;r-=(r&(-r))) ret^=t[r];
return ret;
}

void add(int i, int k)
{
for (;i <= n; i += (i & -i)) t[i]^=k;
}

int main()
{
scanf("%d", &n);
for (int i = 1; i <=n;++i)
{
scanf("%d", &a[i]);
sum[i] = sum[i - 1] ^ a[i];
}
int m;
scanf("%d", &m);
for (int i = 1; i<=m;++i)
{
int l, r;
scanf("%d%d", &l, &r);
g[r].push_back({l,i});//c++11写法
}

for (int i = 1; i <= n; ++ i)
{
if (mp.count(a[i]))
{
add(mp[a[i]], a[i]);
}
mp[a[i]] = i;
add(mp[a[i]], a[i]);
for (auto j : g[i])
{
int tmp = sum[i] ^ sum[j.l -1];
ans[j.id] = tmp ^ ask(j.l,i);
}
}
for (int i = 1; i <= m; ++ i)
printf("%d\n", ans[i]);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: