期末后恢复性训练,结果完美爆炸。。。
A,题意:2n个人,分成两队,要求无论怎么分配,第一队打赢第二队
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pii pair<int,int> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-12; const int N=1000+10,maxn=90000+10,inf=0x3f3f3f3f; int a[N]; int main() { int n; scanf("%d",&n); for(int i=0;i<2*n;i++)scanf("%d",&a[i]); sort(a,a+2*n); if(a[n-1]==a[n])puts("NO"); else puts("YES"); return 0; } /******************** ********************/
B题意:有一个6位数,要求改最少的数使得前3个加起来等于后三个加起来
题解:瞎搞都行,我是直接从0for到1000000找最小
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pii pair<int,int> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-12; const int N=1000000+10,maxn=90000+10,inf=0x3f3f3f3f; int a[N]; int main() { int n; scanf("%d",&n); int minn=6; for(int i=0;i<1000000;i++) { int be=i/1000; int en=i%1000; int sum1=0,sum2=0; while(be) { sum1+=be%10; be/=10; } while(en) { sum2+=en%10; en/=10; } if(sum1==sum2) { int di=0,te1=i,te2=n; for(int j=0;j<6;j++) { if(te1%10!=te2%10)di++; te1/=10;te2/=10; } minn=min(minn,di); } } printf("%d ",minn); return 0; } /******************** ********************/
C:题意:你有两台电视机,n个节目,从l到r,可以用不同的电视机看两个节目,但是一个节目结束的同时一个节目开始,不能用同一台电视机看
题解:直接模拟,(刚开始还hash了一下,发现根本没必要,简直是sb)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pii pair<int,int> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-12; const int N=200000+10,maxn=90000+10,inf=0x3f3f3f3f; struct point{ int l,r; bool operator <(const point &rhm)const{ if(l!=rhm.l)return l<rhm.l; return r<rhm.r; } }p[N]; int main() { int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d",&p[i].l,&p[i].r); sort(p,p+n); int t1=-1,t2=-1; for(int i=0;i<n;i++) { if(t1<p[i].l) { t1=p[i].r; } else { if(t2<p[i].l)t2=p[i].r; else { puts("NO"); return 0; } } } puts("YES"); return 0; } /******************** ********************/
D:题意:你在考驾照,有“限速x,不限速,可以超车,不可以超车”四种牌子,你有6种操作,前面四个和超车和改变速度,问最小的忽略牌子能满足交规的个数
题解:直接模拟,超车和超速可以分开考虑,超速用栈保存,超车直接加即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pii pair<int,int> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) #define y1 y2 using namespace std; const double g=10.0,eps=1e-12; const int N=200000+10,maxn=200000+10,inf=0x3f3f3f3f; struct event{ int id,sp; }e[N]; int over[N]; int main() { int n; scanf("%d",&n); int cnt1=0,cnt2=0; for(int i=0;i<n;i++) { int a,b=0; scanf("%d",&a); if(a==1||a==3)scanf("%d",&b); if(a==1||a==3||a==5)e[cnt1++]={a,b}; else over[cnt2++]=a; } int ans=0,i=cnt2-1; while(i>=0) { if(over[i]==2) { i--; while(i>=0&&over[i]==6)i--,ans++; } else i--; } int speed=0; stack<int>s; for(int i=0;i<cnt1;i++) { if(e[i].id==1) { speed=e[i].sp; while(!s.empty()&&speed>s.top()) { s.pop(); ans++; } } else if(e[i].id==3) { s.push(e[i].sp); while(!s.empty()&&speed>s.top()) { s.pop(); ans++; } } else { while(!s.empty())s.pop(); } } printf("%d ",ans); return 0; } /******************** ********************/
E:题意:有n*m的块,k个点着火了,每分钟一个点扩散到其他八个点,问找一个点,使得的最小扩散全部的时间
题解:二分答案,判断可行时,先离散化,要注意加上x+q+1的情况,因为中间可能会有两个连起来的情况,然后扫描线跑一边,找没有覆盖的最大矩形,看能不能满足条件
(由于没有考虑x+q+1的情况,导致花了一个下午找bug = = )
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pii pair<int,int> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-12; const int N=5000+10,maxn=4000+10,inf=0x3f3f3f3f; struct point{ int x,y; }p[N]; int n,m,k; int dp[maxn][maxn]; bool ok(int q) { vector<int>vx,vy; vx.pb(1),vx.pb(n); vy.pb(1),vy.pb(m); for(int i=0;i<k;i++) { int x1=max(1,p[i].x-q); int x2=min(n,p[i].x+q); vx.pb(x1); if(x1-1>1)vx.pb(x1-1); if(x2+1<n)vx.pb(x2+1); int y1=max(1,p[i].y-q); int y2=max(m,p[i].y+q); vy.pb(y1); if(y1-1>1)vy.pb(y1-1); if(y2+1<m)vy.pb(y2+1); } sort(vx.begin(),vx.end()); vx.resize(unique(vx.begin(),vx.end())-vx.begin()); sort(vy.begin(),vy.end()); vy.resize(unique(vy.begin(),vy.end())-vy.begin()); memset(dp,0,sizeof dp); for(int i=0;i<k;i++) { int x1=max(1,p[i].x-q); int x2=min(n,p[i].x+q)+1; int y1=max(1,p[i].y-q); int y2=min(m,p[i].y+q)+1; x1=lower_bound(vx.begin(),vx.end(),x1)-vx.begin()+1; x2=lower_bound(vx.begin(),vx.end(),x2)-vx.begin()+1; y1=lower_bound(vy.begin(),vy.end(),y1)-vy.begin()+1; y2=lower_bound(vy.begin(),vy.end(),y2)-vy.begin()+1; dp[x1][y1]++;dp[x2][y2]++; dp[x1][y2]--,dp[x2][y1]--; } int xmax=0,xmin=vx.size()+1,ymax=0,ymin=vy.size()+1; for(int i=1;i<=vx.size();i++) { for(int j=1;j<=vy.size();j++) { dp[i][j]+=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]; if(dp[i][j]==0) { xmax=max(xmax,i); xmin=min(xmin,i); ymax=max(ymax,j); ymin=min(ymin,j); } } } if(xmax==0)return 1; int d=max(vx[xmax-1]-vx[xmin-1],vy[ymax-1]-vy[ymin-1]); if(d&1)++d; d/=2; return d<=q; } int main() { scanf("%d%d%d",&n,&m,&k); for(int i=0;i<k;i++) scanf("%d%d",&p[i].x,&p[i].y); // printf("%d ",ok(3)); int l=-1,r=max(n,m)+1; while(l<r-1) { int mid=(l+r)>>1; if(ok(mid))r=mid; else l=mid; } printf("%d ",r); return 0; } /******************** ********************/
G:题意:有一个无向带权有环图,每两个点之间距离是该路径上的边的权值的异或和,求1到n的最小距离
题解:这题和bzoj2115很相似,可以用线型基求解,先随便找到一条从1到n的路径,记录异或和,把该路径上的环也记录下来,然后对环的所有权值求线型基,最后贪心的选取线型基来和答案异或取最小值
那么,为什么随便找一条路径就可以呢,现在假设有另一条路径更优,那么更优路径和选取的路径构成了一个环,那么如果我们选了这个环,那么异或和就变成更优的那个路径,因此答案还是最小的
线型基在这题中的主要意义是利用最高位的1位置不相同来,使答案中和线型基最高位相同的为1的地方进行异或,这样答案就一定会减小
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pii pair<int,int> #define ull unsigned long long //#define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) #define y1 y2 using namespace std; const double g=10.0,eps=1e-12; const int N=200000+10,maxn=200000+10,inf=0x3f3f3f3f; struct edge{ int to,Next,v; }e[N*2]; int head[N],cnt; void add(int u,int v,int c) { e[cnt].to=v; e[cnt].v=c; e[cnt].Next=head[u]; head[u]=cnt++; } bool vis[N]; int dis[N]; vector<int>v; void dfs(int u) { vis[u]=1; for(int i=head[u];~i;i=e[i].Next) { int x=e[i].to; if(!vis[x]) { dis[x]=dis[u]^e[i].v; dfs(x); } else { v.pb(dis[x]^dis[u]^e[i].v); if(v[v.size()-1]==0)v.pop_back(); } } } int main() { int n,m; scanf("%d%d",&n,&m); memset(head,-1,sizeof head); cnt=0; for(int i=0;i<m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); } dfs(1); // for(int i=0;i<v.size();i++)cout<<v[i]<<"++++"<<endl; // cout<<dis[n]<<endl; vector<int>base; for(int i=0;i<v.size();i++) { int te=v[i]; for(int j=0;j<base.size();j++) te=min(te,te^base[j]); if(te)base.pb(te); } sort(base.begin(),base.end()); for(int i=base.size()-1;i>=0;i--) { int k=0,te=base[i]; while(te)te/=2,k++; k--; // cout<<k<<" "<<base[i]<<" "<<((dis[n]>>k)&1)<<endl; if(((dis[n]>>k)&1))dis[n]^=base[i]; } printf("%d ",dis[n]); return 0; } /******************** ********************/