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; }
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; }
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; }