Codeforces #Pi div2 only

2015-08-08 22:06:48

传送门

赛后补的一场

A、B题水。

C题,只要正着、反着扫一遍,再统计答案就可以了。

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

#define getmid(l,r) ((l) + ((r) - (l)) / 2)
#define MP(a,b) make_pair(a,b)
#define PB push_back

typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int INF = (1 << 30) - 1;
const int MAXN = 200010;

int n,k;
ll A[MAXN];
int L[MAXN],R[MAXN];
map<ll,int> mp;

int main(){
    scanf("%d%d",&n,&k);
    for(int i = 1; i <= n; ++i){
        int a;
        scanf("%d",&a);
        A[i] = (ll)a;
    }
    for(int i = 1; i <= n; ++i){
        if(A[i] % k == 0){
            L[i] = mp[A[i] / k];
        }
        mp[A[i]]++;
    }
    mp.clear();
    for(int i = n; i >= 1; --i){
        R[i] = mp[A[i] * k];
        mp[A[i]]++;
    }
    ll ans = 0;
    for(int i = 1; i <= n; ++i){
        ans += (ll)L[i] * R[i];
    }
    printf("%I64d\n",ans);
    return 0;
}
View Code

 

D题:技巧题,用 set 维护一下。

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

#define getmid(l,r) ((l) + ((r) - (l)) / 2)
#define MP(a,b) make_pair(a,b)
#define PB push_back

typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int INF = (1 << 30) - 1;
const int MAXN = 200010;

int m,n,k,a;
int X[MAXN];

set<int> st;
set<int>::iterator it;

int main(){
    scanf("%d%d%d",&n,&k,&a);
    st.insert(0);
    st.insert(n + 1);
    scanf("%d",&m);
    for(int i = 1; i <= m; ++i) scanf("%d",X + i);
    int ans = (n + 1) / (a + 1);
    for(int i = 1; i <= m; ++i){
        it = st.lower_bound(X[i]);
        int p1,p2 = (*it);
        it--;
        p1 = (*it);
        int cnt = (p2 - p1) / (a + 1);
        int pre = (X[i] - p1) / (a + 1);
        int nxt = (p2 - X[i]) / (a + 1);
        st.insert(X[i]);
        ans = ans - cnt + pre + nxt;
        if(ans < k){
            printf("%d\n",i);
            return 0;
        }
    }
    printf("-1\n");
    return 0;
}
View Code

 

E题:最短路,桥

  题意:给出一个有向图,要从 s 点走到 t 点(走最短路),问对于每条边,是否必定会被经过,如果不是必定经过,那么最小减少多少边权能使其必定被经过(边权不能减少到0)

  思路:首先是找最短路,根据最短路上的边再建图,找出其中的桥,就是必定经过的边(当然可以通过另外的方法:最短路计数来解决)

  然后检索所有的边,看他的边权减少到多少才能比最短路小,这个可以通过预先处理出起点到每个点的最短距离,和终点到每个点的最短距离来实现。

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

#define getmid(l,r) ((l) + ((r) - (l)) / 2)
#define MP(a,b) make_pair(a,b)
#define PB push_back

typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int INF = (1 << 30) - 1;
const int MAXN = 100010;

int n,m,s,t,tot;
ll dis[2][MAXN];
int first[2][MAXN],ecnt[2];
int First[MAXN],Ecnt;
int dfn[MAXN],low[MAXN];
int ans[MAXN];
int tag[MAXN << 1];

struct edge{
    int u,v,next,c,id;
}e[2][MAXN << 1],E[MAXN << 1];

inline void add_edge(int u,int v,int c){
    e[0][ecnt[0]].next = first[0][u];
    e[0][ecnt[0]].u = u;
    e[0][ecnt[0]].v = v;
    e[0][ecnt[0]].c = c;
    first[0][u] = ecnt[0]++;

    e[1][ecnt[1]].next = first[1][v];
    e[1][ecnt[1]].u = v;
    e[1][ecnt[1]].v = u;
    e[1][ecnt[1]].c = c;
    first[1][v] = ecnt[1]++;
}

inline void Add_edge(int u,int v,int id){
    E[Ecnt].next = First[u];
    E[Ecnt].v = v;
    E[Ecnt].id = id;
    First[u] = Ecnt++;
}

void Dfs(int p,int pre){
    dfn[p] = low[p] = ++tot;
    for(int i = First[p]; ~i; i = E[i].next){
        int v = E[i].v;
        if(tag[i]) continue;
        tag[i] = tag[i ^ 1] = 1;
        if(!dfn[v]){
            Dfs(v,p);
            low[p] = min(low[p],low[v]);
            if(low[v] > dfn[p]){
                ans[E[i].id] = 0;
            }
        }
        else low[p] = min(low[p],dfn[v]);
    }
}

void Tarjan(){
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    for(int i = 1; i <= n; ++i){
        if(!dfn[i]) Dfs(i,0);
    }
}

struct cmp{
    bool operator ()(pii a,pii b){
        return a.first > b.first;
    }
};

void Dijstra(int s,int f){
    priority_queue<pii,vector<pii >,cmp> PQ;
    dis[f][s] = 0;
    PQ.push(MP(dis[f][s],s));
    while(!PQ.empty()){
        pii x = PQ.top(); PQ.pop();
        if(dis[f][x.second] < x.first) continue; //当前的x并非最短路径,舍弃
        for(int i = first[f][x.second]; i != -1; i = e[f][i].next){
            int v = e[f][i].v;
            if(dis[f][v] > dis[f][x.second] + e[f][i].c){
                dis[f][v] = dis[f][x.second] + e[f][i].c;
                PQ.push(MP(dis[f][v],v));
            }
        }
    }
}

int main(){
    memset(tag,0,sizeof(tag));
    memset(ans,-1,sizeof(ans));
    memset(First,-1,sizeof(First));
    memset(first,-1,sizeof(first));
    ecnt[0] = ecnt[1] = Ecnt = tot = 0;
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int o = 1; o <= m; ++o){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add_edge(a,b,c);
    }
    for(int i = 1; i <= n; ++i) dis[0][i] = dis[1][i] = 1LL << 50;
    Dijstra(s,0);
    Dijstra(t,1);
    ll tmin = dis[0][t];
    for(int o = 0; o < ecnt[0]; ++o){
        int u = e[0][o].u;
        int v = e[0][o].v;
        ll ned = tmin - dis[0][u] - dis[1][v];
        if(ned > 1){
            ans[o] = e[0][o].c - ned + 1;
        }
        if(ned == e[0][o].c){
            Add_edge(e[0][o].u,e[0][o].v,o);
            Add_edge(e[0][o].v,e[0][o].u,o);
        }
    }
    Tarjan();
    for(int i = 0; i < ecnt[0]; ++i){
        if(ans[i] == 0) printf("YES\n");
        else if(ans[i] == -1) printf("NO\n");
        else printf("CAN %d\n",ans[i]);
    }
    return 0;
}
View Code

 

posted @ 2015-08-08 22:20  Naturain  阅读(115)  评论(0编辑  收藏  举报