暑假第三测

题解:

第一题:二分, 因为配对是肯定的,距离递增;这道题我用的斜率,他没有卡精度,所以可以用三角形算乘法更优

若P在某条线外面,则他与线端点形成的三角形>线形成的三角形, 否则为小于;

条件是  Y[i] * Xp + X[i] * Yp >= X[i]*Y[i];

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int M = 1e5 +10;
double x[M], y[M], k[M];
double x1, yy, k1;
bool check(int t){
    double x2 = y[t]/(k1 - k[t]);
    double y2 = k1*x2;
    if(x2 <= x1 && y2 <= yy)return 1;
    return 0;
}

int main()
{
    freopen("geometry.in","r",stdin);
    freopen("geometry.out","w",stdout);
    int n, m;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)scanf("%lf", &x[i]);
    for(int i = 1; i <= n; i++)scanf("%lf", &y[i]);
    sort(x+1, x+1+n); sort(y+1, y+1+n);
    for(int i = 1; i <= n; i++)
        k[i] = -y[i]/x[i];
        
    scanf("%d", &m);
    while(m--){
        scanf("%lf%lf", &x1, &yy);
        k1 = yy/x1;
        int lf = 1, rg = n, ans = 0;
        while(lf <= rg){
            int mid = (lf + rg) >> 1;
            if(check(mid))ans = mid, lf = mid + 1;
            else rg = mid - 1;
        }
        printf("%d
", ans);
    }
    return 0;
}
View Code

第二题:dp, dp[u]表示U到根的最小距离, 且在U点买票;

最开始想的是某个点有选和不选, dp[u][1] = dp[u可以到达的地方][1/0]  dp[u][0] = ??? (0 buy, 1 not buy);

就不会转移了; 

#include <bits/stdc++.h>
const int M = 1e5 + 10, P = 20, inf = 2e9;
using namespace std;
int mi[M], h[M], dp[M], anc[M][P+1], ch[M][P+1], tot;
void read(int &x){
    x=0;int f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    x*=f;
}
struct node{int k, w;};
struct edge{int v,nxt;}G[M];
void add(int u, int v){G[++tot].nxt = h[u]; h[u] = tot; G[tot].v = v; }
vector <node> vec[M];
void dfs(int u, int f){
    dp[u] = inf;
    anc[u][0] = f; ch[u][0] = dp[f];
    for(int i = 1; i <= P; i++)ch[u][i] = inf;
    for(int i = 1; i <= P; i++)
        anc[u][i] = anc[anc[u][i-1]][i-1];
    for(int i = 1; i <= P; i++)
        ch[u][i] = min(ch[anc[u][i-1]][i-1], ch[u][i-1]);

    if(u == 1)dp[u] = 0;
    else {
        int siz = vec[u].size(), i;
        for(i = 0; i < siz; i++){
            int dis = vec[u][i].k;
            int j = P, now = u, tmp = inf;
            while(now && dis){
                while(mi[j] > dis && j >= 0)j--;
                dis -= mi[j];
                tmp = min(tmp, ch[now][j]);
                now = anc[now][j];
            }
            dp[u] = min(dp[u], tmp + vec[u][i].w);
        }
    }
    
    for(int i = h[u]; i; i = G[i].nxt){
        int v = G[i].v;
        dfs(v, u);
    }

}

int main()
{
    freopen("party.in","r",stdin);
    freopen("party.out","w",stdout);
    mi[0] = 1;
    //for(int i = 0; i <= P; i++)ch[0][i] = inf; 
    int n, m, q;
    read(n), read(m);
    for(int i = 1; i < M; i++)mi[i] = mi[i-1]*2;
    for(int i = 1; i < n; i++){
        int u, v;
        read(u), read(v);
        add(v, u);
    }
    for(int i = 1; i <= m; i++){
        int v, k, w;
        read(v), read(k), read(w);
        vec[v].push_back((node){k, w});
    }
    dfs(1, 0);
    //for(int i = 1; i <= n; i++)printf("%d ", dp[i]);
    read(q);
    while(q--){
        int x; read(x);
        printf("%d
", dp[x]);
    }
    return 0;
}
View Code

  

第三题:带区间的splay, 又是zjj同学帮我看出来的,万分感谢啊~~  细节地方还要仔细思考,尤其是鼠标的操作

还有 字符数组不能swap之类的骚气操作, 字符串不可以减

#include <bits/stdc++.h>

using namespace std;
string s;
const int M = 5 * 1e6;
int len, root, p[2], tot=1;
char s1[M];
struct Splay{
    int fa[M], lazy[M], ch[M][2], siz[M];
    char val[M];

    inline void up(int x){ siz[x] = siz[ch[x][0]] + siz[ch[x][1]]+ 1; }
    inline void down(int x){
        if(!lazy[x])return;
        swap(ch[x][0], ch[x][1]);
        lazy[ch[x][0]]^=1; lazy[ch[x][1]]^=1;
        lazy[x] = 0;
    }
    int build(int f,int x, int l = 1, int r = len+2){
        if(l > r)return 0;
        int mid = (l + r) >> 1;
        fa[x] = f;
        val[x] = s1[mid];
        ch[x][0] = build(x,++tot, l, mid-1);
        ch[x][1] = build(x,++tot, mid+1, r);
        up(x);
        return x;
    }

    void rotate(int x, int d){
        int y = fa[x];
        down(y);down(x);
        ch[y][d^1] = ch[x][d];
        if(ch[x][d]) fa[ch[x][d]] = y;
        fa[x] = fa[y];
        if(fa[y]) ch[fa[y]][y == ch[fa[y]][1]] = x;
        ch[x][d] = y, fa[y] = x;
        up(y);
        up(x);
    }

    void splay(int x, int targt = 0){
        while(fa[x] != targt){
            int y = fa[x];
            if(x == ch[y][0]){
                if(y == ch[fa[y]][0] && fa[y] != targt)
                    rotate(y, 1);
                rotate(x, 1);
            }
            else{
                if(y == ch[fa[y]][1] && fa[y] != targt)
                    rotate(y, 0);
                rotate(x, 0);
            }
        }
        if(!targt)root = x;
    }

    void print(int now){
        if(!now)return;
        down(now);
        print(ch[now][0]);
        if(val[now] >= 33 && val[now] <= 126)printf("%c", val[now]);
        //cout<<now<<" "<<val[now]<<endl;
        print(ch[now][1]);
    }

    int find(int x){
        int now = root;
        while(1){
            if(!now)return 0;
            down(now);
            int t = siz[ch[now][0]];
            if(x <= t)now = ch[now][0];
            else if(x >= t + 2){
                x -= (t+1);
                now = ch[now][1];
            }
            else return now;
        }

    }

    void insert(int pos, char v){
        int ln = find(pos - 1), rn = find(pos);
        splay(ln); splay(rn, ln);
        ch[rn][0] = ++tot;
        //cout<<val[ln]<<endl;
        siz[tot] = 1;
        val[tot] = v;
        fa[tot] = rn;
        up(rn);up(ln);
    }

    void del(int pos){
        int ln = find(pos), rn = find(pos + 2);
        splay(ln); splay(rn, ln);
        ch[rn][0] = 0;
        up(rn);up(ln);
    }

    void rev(int lf, int rg){
        int ln = find(lf), rn = find(rg);
        splay(ln); splay(rn, ln);
        int pp = ch[rn][0];
        lazy[pp]^=1;
        up(rn);up(ln);
    }

}Tr;
inline int dir(){
    getchar();
    return getchar( ) == 'L' ? 0 : 1;
}
void Lmove(){
    int t = dir();
    if(p[t] == 1){puts("F");return;}
    puts("T"); p[t]--;
}
void Rmove(){
    int t = dir();
    if(p[t] == len+1){puts("F");return;}
    puts("T"); p[t]++;
}
void Insert(){
    int t = dir();getchar(); char val = getchar();
    Tr.insert(p[t]+1, val);
    len++;
    if(p[t^1] >= p[t])p[t^1]++;
    p[t]++;puts("T");
}
void Del(){
    int t = dir();
    if(p[t] == len+1){puts("F");return;}
    puts("T"); 
    if(p[t^1] > p[t]) p[t^1]--;
    len--;
    Tr.del(p[t]);
}
void Rev(){
    if(p[0] >= p[1]){puts("F");return;}
    Tr.rev(p[0], p[1]+1);
    puts("T");
}
void print(){
    Tr.print(root);
    printf("
");
}
int main()
{
    freopen("editor.in","r",stdin);
    freopen("editor.out","w",stdout);
    cin>>s;
    char rp=3;
    len = s.size();  
    s1[1]=rp;
    s1[tot]=rp;
    for (int i = 2; i <= len + 1; i++) 
    {
        s1[i]=s[i-2];
    }
    root = Tr.build(0,1);
    int n;
    scanf("%d", &n);
    p[0] = 1; p[1] = len+1;
    while(n--)
    {
        char opt, gb, zm;
        scanf("
%c", &opt);
        switch(opt){
            case 'S':{print();break;}
            case '<':{Lmove();break;}
            case '>':{Rmove();break;}
            case 'I':{Insert();break;}
            case 'D':{Del();break;}
            case 'R':{Rev();break;}
        }
        //print();
       // cout<<p[0]<<" "<<p[1]<<" "<<len<<endl;
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/EdSheeran/p/9311103.html