题目大意:按时间顺序出现靶子和射击一个位置,靶子的圆心为(x, y)半径为r,即圆与x轴相切,靶子不会重叠,靶子被击中后消失,
每次射击找出哪个靶子被射中,或者没有射中靶子。
思路:关键点在于,圆都与x轴相切,那么我们能发现,如果射击在(x, y) 这个点,包含它的圆只可能是它左边第一个直径>= y的圆c1,
或者是它右边第一个直径 >=y 的圆c2,因为在c1 和 c2之间的圆不可能覆盖到(x, y), 因为它们的直径小于y,在c1左边和c2右边的圆
通过画图我们也能得出不肯能包含(x, y),那么每次射击我们只需要check两个圆就好了。
找圆的过程能用线段树维护,加入一个圆就在线段树对应的x的位置的值变成2*r,然后通过二分用线段树找圆,最后判一下是否在圆内。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> using namespace std; const int N = 2e5 + 7; const int M = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int n, tot, mx[N << 2], X[N], hs[N]; struct Qus { int op, x, y; } qus[N]; void update(int pos, int v, int l, int r, int rt) { if(l == r) { mx[rt] = v; return; } int mid = l + r >> 1; if(pos <= mid) update(pos, v, l, mid, rt << 1); else update(pos, v, mid + 1, r, rt << 1 | 1); mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]); } int getMx(int L, int R, int l, int r, int rt) { if(l >= L && r <= R) return mx[rt]; int mid = l + r >> 1, ans = 0; if(L <= mid) ans = max(ans, getMx(L, R, l, mid, rt << 1)); if(R > mid) ans = max(ans, getMx(L, R, mid + 1, r, rt << 1 | 1)); return ans; } bool check(int x, int y, int id) { LL dis1 = 1ll * qus[id].y * qus[id].y; LL dis2 = 1ll * (x - qus[id].x) * (x - qus[id].x) + 1ll * (y - qus[id].y) * (y - qus[id].y); return dis1 > dis2; } int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d%d%d", &qus[i].op, &qus[i].x, &qus[i].y); hs[++tot] = qus[i].x; } sort(hs + 1, hs + 1 + tot); tot = unique(hs + 1, hs + 1 + tot) - hs - 1; for(int i = 1; i <= n; i++) { int op = qus[i].op, x = qus[i].x, y = qus[i].y; int pos = lower_bound(hs + 1, hs + 1 + tot, x) - hs; if(op == 1) { X[pos] = i; update(pos, 2 * y, 1, tot, 1); } else { int l = 1, r = pos, ret = -1; while(l <= r) { int mid = l + r >> 1; if(getMx(mid, pos, 1, tot, 1) >= y) ret = mid, l = mid + 1; else r = mid - 1; } if(ret != -1 && check(x, y, X[ret])) { printf("%d\n", X[ret]); update(ret, 0, 1, tot, 1); continue; } l = pos, r = tot, ret = -1; while(l <= r) { int mid = l + r >> 1; if(getMx(pos, mid, 1, tot, 1) >= y) ret = mid, r = mid - 1; else l = mid + 1; } if(ret != -1 && check(x, y, X[ret])) { printf("%d\n", X[ret]); update(ret, 0, 1, tot, 1); continue; } puts("-1"); } } return 0; }
题目大意:问长宽高为a, b, c的立方体,能不能用n * m的纸折出来。
思路:暴力枚举判断。。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> using namespace std; const int N = 1000 + 7; const int M = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int n, m, a[3], id[3]; bool check(int x, int y) { if(x <= n && y <= m) return true; if(x <= m && y <= n) return true; return false; } int main() { scanf("%d%d%d", &a[0], &a[1], &a[2]); id[0] = 0, id[1] = 1, id[2] = 2; scanf("%d%d", &n, &m); sort(a, a + 3); do { int x = a[id[0]], y = a[id[1]], z = a[id[2]]; if(check(2 * z + x, 2 * y + 2 * z)) { puts("Yes"); return 0; } if(check(x + y + z, 2 * x + y + z)) { puts("Yes"); return 0; } if(check(2 * z + x, x + 2 * y + z)) { puts("Yes"); return 0; } if(check(3 * y + x + z, x + z)) { puts("Yes"); return 0; } } while(next_permutation(id, id + 3)); puts("No"); return 0; } /* 2z + x 2y + 2z x + y + z 2x + y + z 2z + x x + 2y + z */
题目大意:给你一个 n 个点 m (m >= 2 * n)条边的有向图,且原图为一个强连通分量,要求你选出2 * n条边,其他的删掉仍然是一个
强连通分量。
思路:比赛的时候我没想到,队友想出来的。。 用1号点跑一遍图,建反边用1号点再跑一次就好了。 应该挺听容易想到的,题目说2 * n
应该想到由两个树组成。
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000007 #define ld long double #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double eps=1e-6; const int N=100000+10,maxn=500000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; vector<pair<int,int> >v[N],rev[N]; pii p[N]; bool vis[N],used[N]; void dfs(int u) { vis[u]=1; for(int i=0;i<v[u].size();i++) { int x=v[u][i].fi; if(!vis[x]) { used[v[u][i].se]=1; dfs(x); } } } void dfs1(int u) { vis[u]=1; for(int i=0;i<rev[u].size();i++) { int x=rev[u][i].fi; if(!vis[x]) { used[rev[u][i].se]=1; dfs1(x); } } } int main() { int T;scanf("%d",&T); while(T--) { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)v[i].clear(),rev[i].clear(); for(int i=0;i<m;i++) { int x,y; scanf("%d%d",&x,&y); v[x].pb(mp(y,i)); rev[y].pb(mp(x,i)); p[i]=mp(x,y); used[i]=0; } memset(vis,0,sizeof vis); dfs(1); memset(vis,0,sizeof vis); dfs1(1); int sum=0; for(int i=0;i<m;i++) if(used[i]) sum++; int now=2*n-sum; for(int i=0;i<m;i++) { if(!used[i]&&now) { now--; used[i]=1; } } for(int i=0;i<m;i++) if(!used[i]) printf("%d %d\n",p[i].fi,p[i].se); } return 0; } /******************** ********************/
题目大意:给你三视图的每个面能看见的方块个数a, b, c,然后构造出这样的图形。
思路:一起想了挺久的,三维立体很难实现,我们就考虑把所有点放一个面里面,构成图形的个数就是max(a, b, c),
斜着放三面个数都加一,横着放两面个数加一,填补空缺一个面加一,构造一下。细节挺多的。。。
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000007 #define ld long double #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double eps=1e-6; const int N=100+10,maxn=500000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; int a[3], b[3]; struct point{ int x,y,z; }; int ok[N][N]; void solve(int x,int y,int z){ vector<point> v; vector<point> ans; for(int i=0;i<x;i++) v.pb({0,i,i}); for(int i=x;i<y;i++) v.pb({0,x-1,i}); for(int i=0;i<v.size();i++)ok[v[i].y][v[i].z]=1; int now=z-y; for(int i=0;i<x;i++) { for(int j=0;j<y;j++) { if(!ok[i][j]&&now) { v.pb({0,i,j}); ok[i][j]=1; now--; } } } if(now!=0){puts("-1");return ;} if(b[0]==a[0]&&b[1]==a[2]&&b[2]==a[1]) { for(int i=0;i<v.size();i++)swap(v[i].x,v[i].y); } else if(b[0]==a[1]&&b[1]==a[0]&&b[2]==a[2]) { for(int i=0;i<v.size();i++)swap(v[i].y,v[i].z); } else if(b[0]==a[1]&&b[1]==a[2]&&b[2]==a[0]) { for(int i=0;i<v.size();i++) { swap(v[i].x,v[i].z); swap(v[i].y,v[i].z); } } else if(b[0]==a[2]&&b[1]==a[0]&&b[2]==a[1]) { for(int i=0;i<v.size();i++) { swap(v[i].x,v[i].y); swap(v[i].y,v[i].z); } } else if(b[0]==a[2]&&b[1]==a[1]&&b[2]==a[0]) { for(int i=0;i<v.size();i++) { swap(v[i].x,v[i].z); } } printf("%d\n",v.size()); for(int i=0;i<v.size();i++) printf("%d %d %d\n",v[i].x,v[i].y,v[i].z); } int main(){ for(int i = 0; i < 3; i++) { scanf("%d", &a[i]); b[i] = a[i]; } sort(a, a + 3); solve(a[0],a[1],a[2]); return 0; } /******************** ********************/
队友写的水题,不知道啥意思。
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000007 #define ld long double #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double eps=1e-6; const int N=20000+10,maxn=500000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; multiset<int>p; int a[N]; int ans[N]; int main() { int n; scanf("%d",&n); for(int i=1,x;i<=n;i++) { scanf("%d",&x); if(x>0)a[x]++; else if(x==0)p.insert(i); else { if(a[-x]>0)a[-x]--; else if(p.size()!=0) { // printf("--%d\n",*p.begin()); ans[*p.begin()]=-x; p.erase(p.begin()); } else return 0*puts("No"); } } while(p.size()!=0)ans[*p.begin()]=1,p.erase(p.begin()); puts("Yes"); for(int i=1;i<=n;i++) if(ans[i]!=0) printf("%d ",ans[i]); puts(""); return 0; } /******************** ********************/
补题****************************************************************************
题目大意,有若干个L形连通块,两边长为n,有一个重叠, 问你最少用几个能把(0 , 0)和(a, b)连起来, L形的物件不能有交叉。
思路:分类讨论贪心,分为一下几种情况。
1.a - x < n && b - y < n 用一个L就能连通
2.a - x > n && b - y > n 贪心地继续连在前一个的末端
3.a - x > n && b - y < n y这维不用贪了,贪x这维。
4.与3相反。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> using namespace std; const int N = 2e5 + 7; const int M = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int T; LL a, b, n; bool flag = false; vector<pair<pair<LL, LL>, pair<LL, LL> > > ans; void dfs(LL x, LL y) { if(a - x < n && b - y < n) { if(!flag) { int x1 = x - (x + n - 1 - a); int y1 = y; int x2 = a; int y2 = y + n - 1; ans.push_back(mk(mk(x2, y2), mk(x1, y1))); return; } else { int x2 = x; int y2 = y - (y + n - 1 - b); int x1 = x + n - 1; int y1 = b; ans.push_back(mk(mk(x2, y2), mk(x1, y1))); } return; } if(b - y < n) { ans.push_back(mk(mk(x + n - 1, y - n + 1), mk(x, y))); flag = true; dfs(x + n, y); return; } if(a - x < n) { ans.push_back(mk(mk(x, y), mk(x - n + 1, y + n - 1))); flag = false; dfs(x, y + n); return; } if(a - x >= n && b - y >= n) { ans.push_back(mk(mk(x + n - 1, y + n - 1), mk(x, y))); if(abs(a - x) >= abs(b - y)) flag = true, dfs(x + n, y + n - 1); else flag = false, dfs(x + n - 1, y + n); return; } } int main() { scanf("%d", &T); while(T--) { ans.clear(); scanf("%lld%lld%lld", &a, &b, &n); int x = a, y = b; if(a < 0) a = -a; if(b < 0) b = -b; dfs(0, 0); for(int i = 0; i < ans.size(); i++) { if(a != x) ans[i].fi.fi = -ans[i].fi.fi, ans[i].se.fi = -ans[i].se.fi; if(b != y) ans[i].fi.se = -ans[i].fi.se, ans[i].se.se = -ans[i].se.se; } printf("%d\n", (int) ans.size()); for(int i = 0; i < ans.size(); i++) { printf("%lld %lld %lld %lld\n", ans[i].fi.fi, ans[i].fi.se, ans[i].se.fi, ans[i].se.se); } } return 0; } /* 1 4 1 3 */