【NOIP模擬】T1+T2+T3
阿新 • • 發佈:2018-12-17
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; }