1. 程式人生 > >暑假第三測

暑假第三測

tdi 端點 tchar png image 乘法 mov int getchar

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

題解:

第一題:二分, 因為配對是肯定的,距離遞增;這道題我用的斜率,他沒有卡精度,所以可以用三角形算乘法更優

技術分享圖片

若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\n", 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\n", 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("\n");
}
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("\n%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

暑假第三測