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

 

【hdu 6579】 1002 

【题目大意】给定一个序列,进行两种操作

 操作0:询问区间l,r之间任意挑选数能够得到的最大异或和

 操作1:输入x,将x ^(上次询问得到的答案)

【解决方案】异或和想到线性基(此处是写了一半的咕了的题解)

  通过储存每个数相对应的线性基的变化(总觉得不是前缀和但是又胜似前缀和),从而解决区间询问的问题

  储存每一个所使用的线性基的位置,从而判断在进行区间询问时,是否能够选取这个数进行线性基变换

  贪心的去找适合的线性基,使序号尽量大(或者说尽量靠近当前节点),从而能够进行区间询问需要得到当前位1的时候,更容易取到

 

#include<cstdio>
#include<algorithm>
#include<iostream>
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<cstdio>
#include<iostream>
#include<algorithm>
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<cstdio>
#include<queue>
#include<cstring>
#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<P, vector<P>, greater<P>>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<cstdio>
#include<vector>
#include<iostream>
#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<P> convex(vector<P> l)
{
    vector<P> 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<P> 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<P> a, vector<P> 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<P> 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

 

 

 

  

 

posted @ 2019-07-24 21:35  rentu  阅读(166)  评论(0编辑  收藏  举报