【map的函数,离线线段树】 codeforces 365 div2

来源:互联网 发布:mt4交易软件下载 编辑:程序博客网 时间:2024/05/16 15:09

不错的文章
写全了map 的各种函数
http://blog.sina.com.cn/s/blog_61533c9b0100fa7w.html

顺便写一下
cf 365 div2 题目

A比大小,谁赢得多谁就赢了,有平局

题意:

#include<iostream>#include<stdio.h>#include<string.h>#include<math.h>#include<algorithm>#include<stdlib.h>#include<queue>#include<stack>#include<map>#include<vector>#define mem(a) memset(a,0,sizeof(a))#define ll __int64#define INF 0x7fffffff   //INT_MAX#define inf 0x3f3f3f3f   //const double PI = acos(-1.0);const double e = exp(1.0);template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }using namespace std;int main(){     int n;     scanf("%d",&n);     int a=0,b=0;     while(n--){         int x,y;         scanf("%d %d",&x,&y);         if(x>y) a++;         if(y>x) b++;     }     if(a>b){         printf("Mishka\n");     }     else if(b>a){         printf("Chris\n");     }     else         printf("Friendship is magic!^^\n");    return 0;}

B
一个无向图, n个城市,形成一个圈。
有k个城市比较特殊,这些个城市要和所有其他的城市都相连起来。每个城市有一个值, 每条边的值 是a*b(起点和终点两个城市值a,b)
虽然一发过,但耗费的时间也委实久了些
可能我写的比较麻烦吧: 用两个前缀和,一个代表总城市价值和
一个代表首都城市 的前缀和。
然后我们先建立起来一个完全图, 再一条边一条边的删除。
对于每一个城市,如果这个城市是首都,则先删去他和其他后面城市的边,再加上他和其他后面的首都的边。然后再加上他和他后面的城市的边。
如果他不是首都,则先删去他和其他城市的边,然后再加上他和所有首都的边,然后再加上他和他后面的城市的边。
总之好像我写的麻烦了。。。

#include<iostream>#include<stdio.h>#include<string.h>#include<math.h>#include<algorithm>#include<stdlib.h>#include<queue>#include<stack>#include<map>#include<vector>#define mem(a) memset(a,0,sizeof(a))#define ll __int64#define INF 0x7fffffff   //INT_MAX#define inf 0x3f3f3f3f   //const double PI = acos(-1.0);const double e = exp(1.0);template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }using namespace std;int f[100005];ll sum[100005];int cap[100005];int flag[100005];ll sum2[100005];int main(){     int n,m;     scanf("%d %d",&n,&m);     __int64 ans=0;     sum[0]=0;     ll all=0;     for(int i=1;i<=n;i++){         scanf("%d",&f[i]);         sum[i]=sum[i-1]+f[i];         ans+=f[i]*sum[i-1];         all+=f[i];     }//   printf("ans=%I64d all=%I64d\n",ans,all);     ll cnt=0;     cap[0]=0;     sum2[0]=0;     for(int i=1;i<=m;i++){         scanf("%d",&cap[i]);         sum2[cap[i]]=sum2[cap[i-1]]+f[cap[i]];         cnt+=f[cap[i]];         flag[cap[i]]=1;     }     for(int i=1;i<=n;i++){         if(!flag[i]){             ans-=(all-sum[i])*f[i];             ans+=cnt*f[i];             int r=i+1;             if(r==n+1) r=1;             if(!flag[r]) ans+=f[i]*f[r];         }         else{             ans-=(all-sum[i])*f[i];             ans+=f[i]*(cnt-sum2[i]);         }//       printf("i=%d %I64d ans=%I64d\n",i,sum[i],ans);     }     printf("%I64d\n",ans);    return 0;}

C
一个多边形以 速度 v 在行驶= =,一个行人 以速度u过马路。然后问最短需要多久时间, 行人可以在半路上随时停 随时走。
一开始以为这是一个计算几何的题目,花了半天,发现好像忽视了随时可以停的条件。
选择的路线依然是笔直的走过去,路线不用去歪着走,就直走。如何要撞上了,我们就站着不动,等一会儿。
我们可以二分答案呢, 二分那个等待时间

因为2e9二分起来也不会太多,那对于每一个时间,我们如何判断呢,我们对于10000个点只要判断一下是否在每一个点的左边,或者在每一个点的右边即可,时间复杂度明显不会太高

注意处理一下别算出负数来了,坐标可能为负。

#include <cstdio>#include <cmath>#include <cstring>#include <ctime>#include <iostream>#include <algorithm>#include <set>#include <vector>#include <sstream>#include <queue>#include <typeinfo>#include<iomanip>#include <fstream>#include <map>#include <stack>#define ll long long#define pb push_back#define all(a) a.begin(), a.end()#define clean(a) memset(a, 0, sizeof(a))typedef long double db;const db eps=1e-9;const int MAXN=10005;using namespace std;struct po{    db x,y;}f[100005];int n;db w,v,u;bool jud(db time){    int l=0,r=0; //左,右边    for(int i=1;i<=n;i++){         if( (time+f[i].y/u )*v > f[i].x){             l=1;//           cout<<time<<"ll "<<f[i].x<<" "<<f[i].y<<endl;         }          else{             r=1;//           cout<<time<<"rr "<<f[i].x<<" "<<f[i].y<<endl;;         }    }    if(l && r)        return 0;    return 1;}int main(){    cin>>n>>w>>v>>u;    for(int i=1;i<=n;i++)        cin>>f[i].x>>f[i].y;    cout<<fixed<<setprecision(12);    if(jud(0)){        cout<<w/u<<endl;        return 0;    }    db l=0,r=2e9;    db ans=w/u;//    cout<<ans<<" ";    int ff=128;    while(ff--){        db mid=(l+r)/2;        if(jud(mid))            r=mid;        else            l=mid;    }    ans+=(l+r)/2;    cout<<ans<<endl;    return 0;}

D
给一个序列
m次询问:
l,r 输出 al…..ar 出现次数为偶数次的 数的异或和

一开始没想清楚,觉得很难;
看了别人的题解
仔细想想发现是没想到点子上: 一段序列 出现次数为偶数次的数异或结果肯定为0;
所以一段序列 异或起来的结果肯定是出现次数为奇数次的数的异或 为 a
我们只要把一段序列去重,即把那些出现次数为偶数次的数变为1个,把出现次数为奇数次的数 变为1个 此为b
我们要求的出现次数为偶数次的数的异或 = a^b
a 一个前缀和 即可 : al…..ar = sum[r]^sum[l-1]
b 如何去重呢,离线的线段树可解决,等我把代码改好看一点再贴出来吧 (逃

0 0
原创粉丝点击