1. 程式人生 > >【NOIP模擬】T1+T2+T3

【NOIP模擬】T1+T2+T3

T1

解析:

       考前15分鐘發現自己讀錯題了是真的爽。。。

       所以就是一道搜尋,當記錄一下當前實際位置和在迴圈圖上的位置,題解也說得很清楚。

程式碼(DFS):

#include <bits/stdc++.h>
using namespace std;

const int fx[5]={0,1,0,-1,0};
const int fy[5]={0,0,1,0,-1};
const int Max=1505;
int t,n,m,sx,sy,ans;
int vis[Max][Max][3];
char mp[Max][Max];
bool flag;

void dfs(int nowx,int nowy,int prex,int prey) //實際位置與在迴圈圖上的位置
{
	if(ans)return;
    if (vis[prex][prey][2] && (vis[prex][prey][0]!=nowx || vis[prex][prey][1]!=nowy)){ans=1;return;}
	//if(vis[prex][prey][2]&&vis[prex][prey][1]==nowy&&vis[prex][prey][0]==nowx) return;
	if(vis[prex][prey][2] && vis[prex][prey][0]==nowx && vis[prex][prey][1]==nowy) return;
	vis[prex][prey][0]=nowx,vis[prex][prey][1]=nowy,vis[prex][prey][2]=1;
	for(int i=1;i<=4;i++) 
	{
	  int x1=prex+fx[i],y1=prey+fy[i];
	  if(mp[(x1+n)%n][(y1+m)%m]!='#') dfs(nowx+fx[i],nowy+fy[i],(x1+n)%n,(y1+m)%m); 
	}
}

int main()
{
	scanf("%d",&t);
	while(t--)
	{
      scanf("%d%d",&n,&m);
	  ans=0;
	  memset(vis,0,sizeof(vis));
	  //scanf("%d%d",&n,&m);
	  for(int i=0;i<n;i++)
	  {
	  	scanf("%s",mp[i]);
	  	for(int j=0;j<m;j++) if(mp[i][j]=='S'){sx=i,sy=j;break;}
	  }
	  dfs(sx,sy,sx,sy);
	  if(ans) puts("Yes");
	  else puts("No");
	}
}

T3

解析:

       瘋狂膜拜ldx大佬:非標準題解

       所以就是線段樹合併,注意L==0的情況根據題解說法會重複算,所以對答案的貢獻即為兩連通塊內個數乘積乘上邊權。

程式碼:

#include <bits/stdc++.h>
using namespace std;

const int Max=200010;
const int Maxm=500010;
int n,m,s,l,tot,p;
long long ans;
int a[Max<<1],num[Max][2],fa[Max];
int tree[Max*50],rt[Max*50][2],lc[Max*50],rc[Max*50];
struct shu{int x,y,z;}e[Maxm];

inline int get_int()
{
	int x=0,f=1;
	char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}

inline int get(int v){return fa[v]==v?v:fa[v]=get(fa[v]);}
inline bool comp(const shu &a,const shu &b){return a.z<b.z;}
inline void lsh()
{
	sort(a+1,a+tot+1);
	tot=unique(a+1,a+tot+1)-a-1;
	for(int i=1;i<=n;i++)
	  num[i][0]=lower_bound(a+1,a+tot+1,num[i][0])-a,num[i][1]=lower_bound(a+1,a+tot+1,num[i][1])-a;
}
inline void init()
{
	n=get_int(),m=get_int(),l=get_int();
	for(int i=1;i<=n;i++)
	  fa[i]=i,a[++tot]=num[i][0]=get_int(),a[++tot]=num[i][1]=num[i][0]+l-1;
	for(int i=1;i<=m;i++) e[i].x=get_int(),e[i].y=get_int(),e[i].z=get_int();
	lsh(),sort(e+1,e+m+1,comp);
}

inline void add(int &root,int l,int r,int x)
{
	if(!root) root=++p;
	tree[root]++;
	if(l==r) return;
	int mid=(l+r)>>1;
	if(x<=mid) add(lc[root],l,mid,x);
	else add(rc[root],mid+1,r,x);
}
inline void Q(int rt1,int rt2,int l,int r,int x)
{
	if(!rt1||!rt2||l==r) return;
	int mid=(l+r)>>1;
	ans+=1ll*x*tree[lc[rt1]]*tree[rc[rt2]];
	Q(lc[rt1],lc[rt2],l,mid,x),Q(rc[rt1],rc[rt2],mid+1,r,x);
}
inline int merge(int rt1,int rt2,int l,int r)
{
	if(!rt1||!rt2) return rt1+rt2;
	tree[rt1]+=tree[rt2];
	if(l==r) return rt1;
	int mid=(l+r)>>1;
	lc[rt1]=merge(lc[rt1],lc[rt2],l,mid),rc[rt1]=merge(rc[rt1],rc[rt2],mid+1,r);
	return rt1;
}

inline void solve()
{
	for(int i=1;i<=n;i++) add(rt[i][0],1,tot,num[i][0]),add(rt[i][1],1,tot,num[i][1]);
	for(int i=1;i<=m;i++)
	{
	  if(get(e[i].x)==get(e[i].y)) continue;
	  int fx=get(e[i].x),fy=get(e[i].y);
	  fa[fy]=fx;
	  if(l) Q(rt[fx][1],rt[fy][0],1,tot,e[i].z),Q(rt[fy][1],rt[fx][0],1,tot,e[i].z);
	  else ans+=1ll*tree[rt[fx][0]]*tree[rt[fy][0]]*e[i].z;
	  rt[fx][1]=merge(rt[fx][1],rt[fy][1],1,tot),rt[fx][0]=merge(rt[fx][0],rt[fy][0],1,tot);
	}
	cout<<ans;
}

int main()
{
	init();
	solve();
	return 0;
}

T3

解析:        哈哈哈。。。這TM是NOIP??!!

       目前完全不可做,等以後再說吧。。。

       還是把程式碼貼上把,不多就500行。。。

程式碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>

using namespace std;

const int N = 100010, INF = 0x7f7f7f7f;

typedef pair<int, int> PII;

#define fi first
#define se second
#define mp make_pair

int n, l, s, t;

namespace A {
    
    inline bool Cmin(int &a, int b) {
        return (!~a || a > b) ? (a = b, 1) : (0);
    }

    struct Node {
        int l, r;
        Node(int l = 0, int r = 0) : l(l), r(r) {}
    };

    bool Cmp1(Node a, Node b) {
        return a.r < b.r;
    }
    bool Cmp2(Node a, Node b) {
        return a.l > b.l;
    }

    vector<Node> sg;

    
    int GetLeft(int s) {
        sort(sg.begin(), sg.end(), Cmp2);
        int l = s;
        for (int i = 0; i < (int)sg.size(); ++i)
            if (sg[i].l < l && l <= sg[i].r) l = sg[i].l;
        return l;
    }
    int GetRight(int s) {
        sort(sg.begin(), sg.end(), Cmp1);
        int r = s;
        for (int i = 0; i < (int)sg.size(); ++i)
            if (sg[i].l <= r && r < sg[i].r) r = sg[i].r;
        return r;
    }

    int main() {
        s %= l;
        t %= l;
        if (s > t) swap(s, t);
        bool p = 0;
        sg.clear();
        for (int i = 1; i <= n; ++i) {
            int l, r;
            scanf("%d%d", &l, &r);
            if (r - l >= ::l) {
                printf("%d\n", min(t - s, s + ::l - t));
                for (++i; i <= n; ++i)
                    scanf("%d%d", &l, &r);
                return 0;
            }
            l %= ::l;
            r %= ::l;
            if (l > r) {
                p = 1;
                sg.push_back(Node(l, ::l - 1));
                sg.push_back(Node(0, r));
            } else if (l < r) sg.push_back(Node(l, r));
        }
        int res = -1;
        if (GetRight(s) >= t) Cmin(res, t - s);
        if (p && !GetLeft(s) && GetRight(t) == l - 1) Cmin(res, s + l - t);
        printf("%d\n", res);
        return 0;
    }
    
}

namespace B {
    
    
    inline bool Cmax(int &a, int b) {
        return (!a || a < b) ? (a = b, 1) : (0);
    }
    inline bool Cmin(int &a, int b) {
        return (!a || a > b) ? (a = b, 1) : (0);
    }

    struct Node1 {
        int x, y;
        Node1(int x = 0, int y = 0) : x(x), y(y) {}
        bool operator < (const Node1 &a) const {
            return y < a.y;
        }
    };

    struct Node2 {
        int l, r, lx, rx;
        Node2(int l = 0, int r = 0, int lx = 0, int rx = 0) : l(l), r(r), lx(lx), rx(rx) {}
        bool operator < (const Node2 &a) const {
            return l < a.l;
        }
    };

    typedef set<Node1>::iterator SNI1;
    typedef pair<SNI1, bool> SM1;

    int sx, sy, tx, ty;
    int sl[N * 4], sr[N * 4], num[N * 4];
    int cnt = 0, tot = 0;
    vector<Node2> v[N * 4];
    bool linkt[N * 4];

    set<Node1> st, ip[N * 4], op[N * 4];

    void Erase1(int t, int l, int r) {
        for (SNI1 i = st.upper_bound(Node1(0, l)); i != st.end() && (*i).y < r; ) {
            Cmax(sr[(*i).x], t);
            st.erase(i++);
        }
        return;
    }
    void Erase2(int t, int l, int r) {
        for (SNI1 i = st.upper_bound(Node1(0, l)); i != st.end() && (*i).y < r; ) {
            Cmin(sl[(*i).x], t);
            st.erase(i++);
        }
        return;
    }

    int Get(int s, int t) {
        if (!v[s].size() || t < v[s][0].l) return -1;
        int k = upper_bound(v[s].begin(), v[s].end(), Node2(t)) - v[s].begin() - 1;
        return (t <= v[s][k].r) ? k : -1;
    }
    bool Link(int s, int x, int y) {
        int k1 = Get(s, x), k2 = Get(s, y);
        return ~k1 && k1 == k2;
    }
    bool GetLeft(int k, SNI1 s, int &x, int &y) {
        if (s != st.begin()) {
            SNI1 t = s;
            --s;
            if (Link(k, s -> y, t -> y)) {
                x = s -> x;
                y = s -> y;
                return 1;
            }
        }
        return 0;
    }
    bool GetRight(int k, SNI1 t, int &x, int &y) {
        if (t != --st.end()) {
            SNI1 s = t;
            ++t;
            if (Link(k, s -> y, t -> y)) {
                x = t -> x;
                y = t -> y;
                return 1;
            }
        }
        return 0;
    }


    namespace Graph {

        int tot, head[N * 6];
        struct Edge {
            int p, nxt, w;
            Edge(int p = 0, int nxt = 0, int w = 0) : p(p), nxt(nxt), w(w) {}
        } edge[N * 35];
        inline void Add_Edge(int u, int v, int w) {
            edge[++tot] = Edge(v, head[u], w);
            head[u] = tot;
            return;
        }
        inline void Add(int u, int v, int w) {
            Add_Edge(u, v, w);
            Add_Edge(v, u, w);
            return;
        }
        void Init() {
            tot = -1;
            memset(head, -1, sizeof(head));
            return;
        }
    
        int dist[N * 6];
        priority_queue<PII> pq;
    
        void Dijkstra(int s) {
            memset(dist, 0x7f, sizeof(dist));
            pq.push(mp(dist[s] = 0, s));
            while (!pq.empty()) {
                PII cur = pq.top();
                pq.pop();
                int u = cur.se;
                if (dist[u] < -cur.se) continue;
                for (int i = head[u]; ~i; i = edge[i].nxt) {
                    int v = edge[i].p, w = edge[i].w;
                    if (dist[v] > dist[u] + w) pq.push(mp(-(dist[v] = dist[u] + w), v));
                }
            }
            return;
        }
    
    }

    int main() {
        for (int i = 1; i <= n; ++i)
            scanf("%d%d", &sl[i], &sr[i]);
        for (int i = 2; i <= n; ++i) {
            sl[i] -= sl[1];
            sr[i] -= sl[1];
        }
        s -= sl[1];
        t -= sl[1];
        sr[1] -= sl[1];
        sl[1] = 0;
        for (int i = 1; i <= cnt; ++i) {
            v[i].clear();
            ip[i].clear();
            op[i].clear();
        }
        memset(linkt, 0, sizeof(linkt));
        if (sr[1] < l) {
            v[cnt = 1].push_back(Node2(0, sr[1]));
            num[1] = 1;
        } else {
            linkt[1] = 1;
            v[1].push_back(Node2(0, l - 1));
            num[1] = 1;
            v[cnt = 2].push_back(Node2(0, sr[1] % l));
        }
        for (int i = 2; i <= n; ++i) {
            if (sr[i - 1] / l == sl[i] / l) {
                num[i] = cnt;
                if (sl[i] / l == sr[i] / l) {
                    v[cnt].push_back(Node2(sl[i] % l, sr[i] % l));
                } else {
                    linkt[cnt] = 1;
                    v[cnt].push_back(Node2(sl[i] % l, l - 1));
                    if (sl[i] / l + 1 == sr[i] / l) {
                        v[++cnt].push_back(Node2(0, sr[i] % l));
                    } else {
                        v[++cnt].push_back(Node2(0, l - 1));
                        if (sr[i] % l < l - 1) {
                            linkt[cnt] = 1;
                            v[++cnt].push_back(Node2(0, sr[i] % l));
                        }
                    }
                }
            } else {
                ++cnt;
                if (sr[i - 1] / l + 1 != sl[i] / l) ++cnt;
                num[i] = cnt;
                if (sl[i] / l == sr[i] / l) {
                    v[cnt].push_back(Node2(sl[i] % l, sr[i] % l));
                } else {
                    v[cnt].push_back(Node2(sl[i] % l, l - 1));
                    if (sl[i] / l + 1 == sr[i] / l) {
                        if (sl[i] % l || sr[i] % l < l - 1) {
                            linkt[cnt] = 1;
                            v[++cnt].push_back(Node2(0, sr[i] % l));
                        }
                    } else {
                        if (sl[i] % l) {
                            linkt[cnt] = 1;
                            v[++cnt].push_back(Node2(0, l - 1));
                        }
                        if (sr[i] % l < l - 1) {
                            linkt[cnt] = 1;
                            v[++cnt].push_back(Node2(0, sr[i] % l));
                        }
                    }
                }
            }
        }
        for (int i = 1; i <= n; ++i)
            if (sl[i] <= s && s <= sr[i]) {
                s -= (s - sl[i]) / l * l;
                if (sl[i] / l == s / l) {
                    sx = num[i];
                } else {
                    sx = num[i] + 1;
                }
                sy = s % l;
                break;
            }
        for (int i = 1; i <= n; ++i)
            if (sl[i] <= t && t <= sr[i]) {
                t -= (t - sl[i]) / l * l;
                if (sl[i] / l == t / l) {
                    tx = num[i];
                } else {
                    tx = num[i] + 1;
                }
                ty = t % l;
                break;
            }
        
        
        memset(sl, 0, sizeof(sl));
        memset(sr, 0, sizeof(sr));
        st.clear();
        tot = 0;
        for (int i = 0; i < (int)v[1].size(); ++i) {
            st.insert(Node1(++tot, v[1][i].l));
            v[1][i].lx = tot;
            sl[tot] = 1;
            if (v[1][i].l != v[1][i].r) {
                st.insert(Node1(++tot, v[1][i].r));
                v[1][i].rx = tot;
                sl[tot] = 1;
            } else v[1][i].rx = v[1][i].lx;
        }
        if (sx == 1) {
            SM1 k = st.insert(Node1(tot + 1, sy));
            if (!k.se) s = (*k.fi).x;
            else s = ++tot;
            Cmin(sl[s], 1);
        }
        if (tx == 1) {
            SM1 k = st.insert(Node1(tot + 1, ty));
            if (!k.se) t = (*k.fi).x;
            else t = ++tot;
            Cmin(sl[t], 1);
        }
        for (int i = 2; i <= cnt; ++i)
            if (v[i].size()) {
                if (v[i][0].l) Erase1(i - 1, -1, v[i][0].l);
                for (int j = 0; j < (int)v[i].size() - 1; ++j)
                    Erase1(i - 1, v[i][j].r, v[i][j + 1].l);
                if (v[i].back().r < l - 1) Erase1(i - 1, v[i].back().r, l);
                for (int j = 0; j < (int)v[i].size(); ++j) {
                    SM1 k = st.insert(Node1(tot + 1, v[i][j].l));
                    Cmin(sl[v[i][j].lx = k.se ? ++tot : (*k.fi).x], i);
                    if (v[i][j].l != v[i][j].r) {
                        k = st.insert(Node1(tot + 1, v[i][j].r));
                        Cmin(sl[v[i][j].rx = k.se ? ++tot : (*k.fi).x], i);
                    } else v[i][j].rx = v[i][j].lx;
                }
                if (sx == i) {
                    SM1 k = st.insert(Node1(tot + 1, sy));
                    if (!k.se) s = (*k.fi).x;
                    else s = ++tot;
                    Cmin(sl[s], i);
                }
                if (tx == i) {
                    SM1 k = st.insert(Node1(tot + 1, ty));
                    if (!k.se) t = (*k.fi).x;
                    else t = ++tot;
                    Cmin(sl[t], i);
                }
            } else Erase1(i - 1, -1, l);
        Erase1(cnt, -1, l);

        
        st.clear();
        for (int i = 0; i < (int)v[cnt].size(); ++i) {
            st.insert(Node1(v[cnt][i].lx, v[cnt][i].l));
            Cmax(sr[v[cnt][i].lx], cnt);
            if (v[cnt][i].l != v[cnt][i].r) {
                st.insert(Node1(v[cnt][i].rx, v[cnt][i].r));
                Cmax(sr[v[cnt][i].rx], cnt);
            }
        }
        if (sx == cnt) {
            st.insert(Node1(s, sy));
            Cmax(sr[s], cnt);
        }
        if (tx == cnt) {
            st.insert(Node1(t, ty));
            Cmax(sr[t], cnt);
        }
        for (int i = cnt - 1; i; --i)
            if (v[i].size()) {
                if (v[i][0].l) Erase2(i + 1, -1, v[i][0].l);
                for (int j = 0; j < (int)v[i].size() - 1; ++j)
                    Erase2(i + 1, v[i][j].r, v[i][j + 1].l);
                if (v[i].back().r < l - 1) Erase2(i + 1, v[i].back().r, l);
                for (int j = 0; j < (int)v[i].size(); ++j) {
                    st.insert(Node1(v[i][j].lx, v[i][j].l));
                    Cmax(sr[v[i][j].lx], i);
                    if (v[i][j].l != v[i][j].r) {
                        st.insert(Node1(v[i][j].rx, v[i][j].r));
                        Cmax(sr[v[i][j].rx], i);
                    }
                }
                if (sx == i) {
                    st.insert(Node1(s, sy));
                    Cmax(sr[s], i);
                }
                if (tx == i) {
                    st.insert(Node1(t, ty));
                    Cmax(sr[t], i);
                }
            } else Erase2(i + 1, -1, l);
        Erase2(1, -1, l);
        
        
        for (int i = 1; i <= cnt; ++i)
            for (int j = 0; j < (int)v[i].size(); ++j) {
                if (v[i][j].lx) {
                    num[v[i][j].lx] = v[i][j].l;
                    ip[sl[v[i][j].lx]].insert(Node1(v[i][j].lx, v[i][j].l));
                    op[sr[v[i][j].lx]].insert(Node1(v[i][j].lx, v[i][j].l));
                }
                if (v[i][j].l != v[i][j].r) {
                    num[v[i][j].rx] = v[i][j].r;
                    ip[sl[v[i][j].rx]].insert(Node1(v[i][j].rx, v[i][j].r));
                    op[sr[v[i][j].rx]].insert(Node1(v[i][j].rx, v[i][j].r));
                }
            }
        num[s] = sy;
        ip[sl[s]].insert(Node1(s, sy));
        op[sr[s]].insert(Node1(s, sy));
        num[t] = ty;
        ip[sl[t]].insert(Node1(t, ty));
        op[sr[t]].insert(Node1(t, ty));
    
    
        Graph::Init();
        st.clear();
        int lx = 0, ly = 0;
        for (SNI1 i = ip[1].begin(); i != ip[1].end(); ++i) {
            int x, y;
            SNI1 t = st.insert(*i).fi;
            if (GetLeft(1, t, x, y)) {
                Graph::Add(x, i -> x, i -> y - y);
            }
            if (GetRight(1, t, x, y)) {
                Graph::Add(x, i -> x, y - i -> y);
            }
        }
        if (st.size() && linkt[1] && v[1].back().l <= st.rbegin() -> y) {
            lx = st.rbegin() -> x;
            ly = st.rbegin() -> y;
        }
        for (SNI1 i = op[1].begin(); i != op[1].end(); ++i)
            st.erase(*i);
        for (int i = 2; i <= cnt; ++i) {
            for (SNI1 j = ip[i].begin(); j != ip[i].end(); ++j) {
                int x, y;
                SNI1 t = st.insert(*j).fi;
                if (GetLeft(i, t, x, y)) {
                    Graph::Add(x, j -> x, j -> y - y);
                }
                if (GetRight(i, t, x, y)) {
                    Graph::Add(x, j -> x, y - j -> y);
                }
            }
            if (st.size() && v[i].size()) {
                if (lx && st.begin() -> y <= v[i][0].r) {
                    Graph::Add(st.begin() -> x, lx, st.begin() -> y + l - ly);
                }
                if (linkt[i] && v[i].size() && v[i].back().l <= st.rbegin() -> y) {
                    lx = st.rbegin() -> x;
                    ly = st.rbegin() -> y;
                } else lx = 0;
            } else lx = 0;
            for (SNI1 j = op[i].begin(); j != op[i].end(); ++j)
                st.erase(*j);
        }
        for (int i = 1; i < cnt; ++i)
            for (int j = 0; j < (int)v[i].size() - 1; ++j)
                if (Link(i + 1, v[i][j].r, v[i][j + 1].l)) Graph::Add(v[i][j].rx, v[i][j + 1].lx, v[i][j + 1].l - v[i][j].r);
        
        
        Graph::Dijkstra(s);
        if (Graph::dist[t] < INF) {
            printf("%d\n", Graph::dist[t]);
        } else puts("-1");
        return 0;
    }
    
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        int type;
        scanf("%d%d%d%d%d", &type, &n, &l, &s, &::t);
        if (!type) A::main();
        else B::main();
    }
    return 0;
}