【hdu 6579】 1002
【题目大意】给定一个序列,进行两种操作
操作0:询问区间l,r之间任意挑选数能够得到的最大异或和
操作1:输入x,将x ^(上次询问得到的答案)
【解决方案】异或和想到线性基(此处是写了一半的咕了的题解)
通过储存每个数相对应的线性基的变化(总觉得不是前缀和但是又胜似前缀和),从而解决区间询问的问题
储存每一个所使用的线性基的位置,从而判断在进行区间询问时,是否能够选取这个数进行线性基变换
贪心的去找适合的线性基,使序号尽量大(或者说尽量靠近当前节点),从而能够进行区间询问需要得到当前位1的时候,更容易取到
#include#include #include using namespace std; const int MAXN = 500010; const int MAXM = 31; int n, m; int ans; int a[MAXN]; int f[MAXN][MAXM], p[MAXN][MAXM]; void insert(int pos,int x) { for (int i = 0; i < MAXM; i++) { f[pos][i] = f[pos - 1][i]; p[pos][i] = p[pos - 1][i]; } int k = pos; for (int i = MAXM; i >= 0; i--) { if (!(x >> i)) continue; if (!f[pos][i]) { f[pos][i] = x; p[pos][i] = k; break; } if (p[pos][i] < k) { swap(f[pos][i], x); swap(p[pos][i], k); } x ^= f[pos][i]; } return; } int main() { int T; scanf("%d", &T); while (T--) { //printf("**\n"); scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); insert(i,a[i]); } ans = 0; for (int i = 1; i <= m; i++) { int op ; scanf("%d", &op); switch (op) { case 0: { int l,r; scanf("%d%d", &l, &r); l = (l^ans) % n + 1; r = (r^ans) % n + 1; if (l > r) swap(l, r); ans = 0; for (int j = MAXM - 1; j >= 0; j--) { if ((ans^f[r][j]) > ans&&p[r][j] >= l) ans ^= f[r][j]; } printf("%d\n", ans); break; } case 1: { n++; scanf("%d", &a[n]); a[n] ^= ans; insert(n,a[n]); break; } default: break; } } for(int i=1;i<=n;i++) for (int j = 0; j < MAXM; j++) { f[i][j] = p[i][j] = 0; } } }
【hdu 6581】1004
【题目大意】一条公路上有一系列编号从1~n的车,给定他们的离斑马线的距离,长度,速度,判断第0号车最晚什么时候能够过斑马线
【解决方案一】
二分答案,直接枚举答案时间,然后从第一辆车递推这个时间是否能够使这辆车安全通过
递推方法,判断前一辆车的位置和自己行驶的距离哪个更远,然后处理
(发现自己还是做题少,基础不牢,这么简单的递推方式都没想出来)
#include#include #include using namespace std; const int MAXN = 100010; const double eps = 1e-11; double s[MAXN], v[MAXN], l[MAXN]; int n; int cmp(double a, double b) { if (b - a > eps) return 1; else { if (fabs(b - a) < eps) return 0; } } int jud(double tim) { double pred = s[n] - tim * v[n]; double dis = 0; for (int i = n-1; i >= 0; i--) { pred = max(s[i] - tim * v[i], pred + l[i+1]); } //过不去,宽限时间 //应该宽限时间,l=mid if (pred > 0) return 0; else return 1; //所有车安全通过 //应该缩减时间,r=mid } int main() { while (scanf("%d", &n)!=EOF) { for (int i = 0; i <= n; i++) { scanf("%lf", &l[i]); } for (int i = 0; i <= n; i++) { scanf("%lf", &s[i]); } for (int i = 0; i <= n; i++) { scanf("%lf", &v[i]); } double l =0, r = s[0]; double ans = 0; for(int i=1;i<100;i++) { double mid = (l + r) / 2; if (jud(mid)) { ans = mid; r = mid - eps; } else { l = mid + eps; } } printf("%.10lf\n",ans); } return 0; }
【解决方案二】
直接从第一辆车开始求取递推,O(n)的复杂度就能够求取的出来
(但是还是不是太懂)
【hdu 6582】1005
最短路+最小割
#include#include #include #define ll long long using namespace std; const int MAXN = 10010; const int MAXM = 20010; const ll INF = (1ll << 62) - 1; typedef pair<int, int> P; struct note { int to; int nt; int rev; ll cal; }; struct edge { note arr[MAXM]; ll dis[MAXN]; int st[MAXN]; int cur[MAXN]; int depth[MAXN]; int top; int n, m, s, t; edge() { memset(st, -1, sizeof(st)); memset(depth, -1, sizeof(depth)); memset(dis, -1, sizeof(dis)); top = 0; } void init() { memset(st, -1, sizeof(st)); memset(depth, -1, sizeof(depth)); memset(dis, -1, sizeof(dis)); top = 0; } void read() { top = 0; scanf("%d%d", &n, &m); s = 1, t = n; for (int i = 1; i <= m; i++) { int x, y; ll z; scanf("%d%d%lld", &x, &y, &z); add(x, y, z); } } bool dep() { queue<int> q; q.push(s); memset(depth, -1, sizeof(depth)); depth[s] = 0; while (!q.empty()) { int v = q.front(); q.pop(); for (int i = st[v]; i != -1; i = arr[i].nt) { int to = arr[i].to; if (!arr[i].cal) continue; if (depth[to] != -1) continue; depth[to] = depth[v] + 1; q.push(to); } } return (depth[t] != -1); } void add(int x, int y, ll z) { top++; arr[top] = { y,st[x],top + 1,z }; st[x] = top; top++; arr[top] = { x,st[y],top - 1,0 }; st[y] = top; } void dijkstra(int start) { priority_queue , greater
>que; fill(dis, dis + MAXN, INF); dis[start] = 0; que.push(P(0, start)); while (!que.empty()) { P p = que.top(); que.pop(); int v = p.second; if (dis[v] < p.first) continue; for (int i=st[v];i!=-1;i=arr[i].nt) { note e = arr[i]; if (!e.cal) continue; if (dis[e.to] > dis[v] + e.cal) { dis[e.to] = dis[v] + e.cal; que.push(P(dis[e.to], e.to)); } } } } ll dfs(int now, ll val) { if (now == t || !val) return val; ll flow = 0; for (int& i = cur[now]; i != -1; i = arr[i].nt) { int to = arr[i].to; if (depth[to] != depth[now] + 1) continue; ll f = dfs(to, min(arr[i].cal, val)); if (!f || !arr[i].cal) continue; flow += f; arr[i].cal -= f; arr[arr[i].rev].cal += f; val -= f; if (!val) return flow; } return flow; } ll dinic() { ll flow = 0; ll f; while (dep()) { for (int i = 1; i <= n; i++) cur[i] = st[i]; while (f = dfs(s, INF)) flow += f; } return flow; } edge& operator=(const edge& a) { n = a.n, m = a.m, s = a.s, t = a.t; for(int i=1;i<=n;i++) for (int j = a.st[i]; j != -1; j = a.arr[j].nt) { int to = a.arr[j].to; if (a.dis[to] - a.dis[i] == a.arr[j].cal) { add(i, to, a.arr[j].cal); } } return *this; } }; edge road; edge new_road; int main() { int T; scanf("%d", &T); while (T--) { road.init(); new_road.init(); road.read(); road.dijkstra(road.s); if (road.dis[road.t] == INF) printf("0\n"); //printf("**\n"); new_road = road; printf("%lld\n", new_road.dinic()); } return 0; }
学习知识点:网络流:最小割
【hdu 6584】 1007
法里数列+同余方程+扩欧
【hdu 6586】 1009
字符串
【hdu 6589】 1012
多项式+卷积
【hdu 6590】 1013
计算几何
#include#include #include #define ll long long using namespace std; const ll eps = 0; const ll lim = 100010; struct V { ll x, y; V(ll a = 0, ll b = 0) :x(a), y(b) {} }; typedef V P; V operator+(V a, V b) { return V(a.x + b.x, b.y + a.y); } V operator-(V a, V b) { return V(a.x - b.x, b.y - a.y); } V operator*(V a, double b) { return V(a.x*b, a.y*b); } V operator*(double a, V b) { return V(a*b.x, b.y*a); } V operator/(V a, double b) { return V(a.x / b, a.y / b); } V operator/(double a, V b) { return V(b.x / a, b.y / a); } ll operator^(V a, V b) { return a.x*b.x + a.y*b.y; } bool operator<(V a, V b) { return (a.x == b.x) ? a.y < b.y : a.x < b.x; } int sgn(ll x) { return (x > eps) - (x < eps); } ll cross(V a, V b) { return a.x*b.y - b.x*a.y; } ll cross(P a, P b, P c) { return cross(b - a, c - a); } struct L { V s, t; L(V a, V b) :s(a), t(b) {} }; ll onL(P p, L l) { return (cross(l.s - p, l.t - p) == 0 && ((l.s - p) ^ (l.t - p)) < 0); } vector convex(vector
l) { vector
ans, s; P tmp(lim, lim); int pos = 0; for (int i = 0; i < l.size(); i++) if (l[i] < tmp) tmp = l[i], pos = i; for (int i = pos, cnt_ = 0; cnt_ < l.size(); cnt_++, i = (i + 1) % l.size()) { while (s.size() >= 2 && sgn(cross(s[s.size() - 2], s[s.size() - 1], l[i])) <= 0) s.pop_back(); s.push_back(l[i]); pos = i; } ans = s; s.clear(); for (int i = pos, cnt_ = 0; cnt_ < l.size(); cnt_++, i = (i - 1) % l.size()) { while (s.size() >= 2 && sgn(cross(s[s.size() - 2], s[s.size() - 1], l[i])) <= 0) s.pop_back(); s.push_back(l[i]); pos = i; } for (int i = 1; i + 1 < s.size(); i++) ans.push_back(s[i]); return ans; } bool P_In_S(P a, vector
b) { int cnt = b.size(); int cnt_ = 0; b.push_back(b[0]); for (int i = 0; i < cnt; i++) { if (onL(a, L(b[i], b[i + 1]))) return true; int k = sgn(cross(a, b[i], b[i + 1])); int d1 = sgn(a.y - b[i].y), d2 = sgn(a.y - b[i + 1].y); if (k < 0 && d1 >= 0 && d2 < 0)cnt_++; if (k > 0 && d2 >= 0 && d1 < 0)cnt_--; } return cnt_ != 0; } bool L_is_Inter(L a, L b) { int c1 = sgn(cross(a.s, a.t, b.s)), c2 = sgn(cross(a.s, a.t, b.t)), c3 = sgn(cross(b.s, b.t, a.s)), c4 = sgn(cross(b.s, b.t, a.t)); if (c1*c2 < 0 && c3*c4 < 0)return true; if (!c1 && onL(b.s, a))return true; if (!c2 && onL(b.t, a))return true; if (!c3 && onL(a.s, a))return true; if (!c4 && onL(a.t, a))return true; return false; } bool IF_inter(vector
a, vector
b) { //printf("1\n"); for (int i = 0; i < a.size(); i++) if (P_In_S(a[i], b)) return true; //printf("2\n"); for (int i = 0; i < b.size(); i++) if (P_In_S(b[i], a)) return true; int cnt1 = a.size(), cnt2 = b.size(); a.push_back(a[0]), b.push_back(b[0]); //printf("3\n"); for (int i = 0; i < cnt1; i++) for (int j = 0; j < cnt2; j++) if (L_is_Inter(L(a[i], a[i + 1]), L(b[j], b[j + 1]))) return true; return false; } int main() { int T; scanf("%d", &T); while (T--) { int n; vector
c1, c2; scanf("%d", &n); for (int i = 1; i <= n; i++) { int y; P tmp; scanf("%lld%lld%d", &tmp.x, &tmp.y, &y); if (y == 1) c1.push_back(tmp); else c2.push_back(tmp); } c1 = convex(c1), c2 = convex(c2); if (IF_inter(c1, c2)) printf("Infinite loop!\n"); else printf("Successful!\n"); } }