杭电多校(一)2019.7.22--暑假集训

【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;
            }
    }
}
View Code

【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;
}
View Code

 

【解决方案二】

  直接从第一辆车开始求取递推,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; }

View Code

 

 学习知识点:网络流:最小割

【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"); } }

View Code

 

 

 

  

 

转载于:https://www.cnblogs.com/rentu/p/11241016.html

你可能感兴趣的:(杭电多校(一)2019.7.22--暑假集训)