B - Link Summon(补)
题意
每一组样例给定五个数字,分别对应1 2 3 4 5的数量,问能凑出多少个6(每个数字都可以当对应数字或者1使用)
思路
由于数字的数量固定,所以为了尽可能凑出多个6,贪心优先选择数量最少的数字配对方式
首先是两个数字:3 3 , 4 2 , 5 x(x代表1~5的所有数字,因为可以当1使用)
然后是三个数字:3 2 x , 4 x y(y同x)
然后是四个数字:2 2 x y , 3 x,y,z
然后是五个数字:2 a b c d(a,b,c,d,e,f同x)
最后是六个数字:a b c d e f(到这一步实际上只剩下1了,为了方便处理还是用变量表示)
这里可以作为1的数字同时也是剩余数字设为sum,那么初始的sum也就是sum/2
假设从配对3 3开始
那么能配对的3就是min(a[3]/2,sum/2) //a[3]可以作为3的剩余量,但是总配对个数不能小于sum/2(因为是两两配对)
假设下一个是配对5 x
那么能配对的5就是min(a[5],sum/2) //5可以作为5也可以作为1,但是总配对个数不能大于sum/2
接下来配对同理
代码
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define u1 (u<<1)
#define u2 (u<<1|1)
#define pb push_back
#define pp pop_back()
#define int long long
#define laile cout<<"laile"<<endl
#define lowbit(x) ((x)&(-x))
#define double long double
#define sf(x) scanf("%lld",&x)
#define sff(x,y) scanf("%lld %lld",&x,&y)
#define sd(x) scanf("%Lf",&x)
#define sdd(x,y) scanf("%Lf %Lf",&x,&y)
#define _for(i,n) for(int i=0;i<(n);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define _pre(i,a,b) for(int i=(a);i>=(b);--i)
#define all(x) (x).begin(), (x).end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef unsigned long long ULL;
typedef pair<int,int>PII;
const int N=1e6+10,INF=4e18;
int n,m;
int a[6];
void solve()
{
int sum=0;
_rep(i,1,5)cin>>a[i],sum+=a[i];
int res=0;
//5 (1234)
m=min(a[5],sum/2);
res+=m;
a[5]-=m;
sum-=m*2;
//4 2
m=min({a[4],a[2],sum/2});
res+=m;
a[4]-=m,a[2]-=m;
sum-=m*2;
//3 3
m=min(a[3]/2,sum/2);
res+=m;
a[3]%=2;
sum-=m*2;
//2 2 2
m=min(a[2]/3,sum/3);
res+=m;
a[2]-=m*3;
sum-=m*3;
//3 2 1
m=min({a[3],a[2],sum/3});
res+=m;
a[3]-=m;
a[2]-=m;
sum-=m*3;
//4 1 1
m=min({a[4],sum/3});
res+=m;
a[4]-=m;
sum-=m*3;
//2 2 1 1
m=min({a[2]/2,sum/4});
res+=m;
a[2]-=m*2;
sum-=m*4;
//3 1 1 1
m=min({a[3],sum/4});
res+=m;
a[3]-=m;
sum-=m*4;
//2 1 1 1 1
m=min({a[2],sum/5});
res+=m;
a[2]-=m;
sum-=m*5;
//其他
cout<<res+sum/6<<'\n';
return ;
}
signed main()
{
IOS;
int T=1;
cin>>T;
while(T--)
solve();
return 0;
}
E - L-Covering Checker
题意
思路
模拟即可,但是要注意‘.’的限制和每个‘C’有且仅对应两个相邻方向的'U''D''L''R',并且'U''D''L''R'不能凭空出现
代码
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define u1 (u<<1)
#define u2 (u<<1|1)
#define pb push_back
#define pp pop_back()
#define int long long
#define laile cout<<"laile"<<endl
#define lowbit(x) ((x)&(-x))
#define double long double
#define sf(x) scanf("%lld",&x)
#define sff(x,y) scanf("%lld %lld",&x,&y)
#define sd(x) scanf("%Lf",&x)
#define sdd(x,y) scanf("%Lf %Lf",&x,&y)
#define _for(i,n) for(int i=0;i<(n);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define _pre(i,a,b) for(int i=(a);i>=(b);--i)
#define all(x) (x).begin(), (x).end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef unsigned long long ULL;
typedef pair<int,int>PII;
const int N=1e6+10,INF=4e18;
int n,m;
int cnt[550][550][4];
char g[550][550];
void solve()
{
cin>>n>>m;
_rep(i,1,n)
_rep(j,1,m)
{
cin>>g[i][j];
_rep(k,0,3)cnt[i][j][k]=0;
}
int pan=0,nowlr=0;
_rep(i,1,n)
_rep(j,1,m)
{
if(g[i][j]=='.')pan++;
else if(g[i][j]=='C')continue;
else
{
nowlr++;
if(g[i][j]=='L')cnt[i][j-1][3]++;
else if(g[i][j]=='U')cnt[i-1][j][0]++;
else if(g[i][j]=='R')cnt[i][j+1][1]++;
else if(g[i][j]=='D')cnt[i+1][j][2]++;
}
}
if(pan!=1||(pan==1&&g[1][m]!='.'))
{
cout<<"No\n";
return;
}
/*
DRC
CLU
*/
_rep(i,1,n)
_rep(j,1,m)
{
if(g[i][j]=='C')
{
int nowcnt=0;
_rep(k,0,3)
nowcnt+=cnt[i][j][k];
nowlr-=nowcnt;
if(nowcnt!=2)
{
cout<<"No\n";
return;
}
else
{
if(!((cnt[i][j][0]&&cnt[i][j][1])||(cnt[i][j][1]&&cnt[i][j][2])||(cnt[i][j][2]&&cnt[i][j][3])||(cnt[i][j][3]&&cnt[i][j][0])))
{
cout<<"No\n";
return;
}
}
}
}
if(nowlr)cout<<"No\n";
else cout<<"Yes\n";
return ;
}
signed main()
{
IOS;
int T=1;
cin>>T;
while(T--)
solve();
return 0;
}
F - Isoball: 2D Version
题意
给定一个矩形以及圆形以及圆形运动方向(vx,vy),判断圆形是否可能被完全落在矩形里面
思路
首先一定从移动圆心解决问题,某个点作为圆心是否合法只需要判断
1.在矩形内
2.到矩形四边距离的最小值>=r即可
题解思路:只需要考虑圆心的位置,因为只要圆心落在 矩阵向内缩r之后的小矩形中,就一定有解,然后问题就变成了圆心运动轨迹所在的射线是否和小矩形有交点,讨论一下交点是否在射线的方向即可解决问题
个人思路(麻烦):如果是正方形那么可以发现最优位置一定是落在对角线和射线交点上(红笔的1情况),但是要特判2的情况,也就是把起点也当做交点加入判断
拓展为矩形之后,变成了四条小正方形的对角线,但是要特判落在矩形中间的情况如射线2,由于射线二到矩形的水平边界一定大于竖直方向边界,所以竖直方向尽量取中点也就是加了一条中间的水平线(由于矩形的长宽位置不同所以又加了一条中间的竖直线)接下来只需要判断射线和六条直线的交点即可
代码
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define u1 (u<<1)
#define u2 (u<<1|1)
#define pb push_back
#define pp pop_back()
#define int long long
#define laile cout<<"laile"<<endl
#define lowbit(x) ((x)&(-x))
#define double long double
#define sf(x) scanf("%lld",&x)
#define sff(x,y) scanf("%lld %lld",&x,&y)
#define sd(x) scanf("%Lf",&x)
#define sdd(x,y) scanf("%Lf %Lf",&x,&y)
#define _for(i,n) for(int i=0;i<(n);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define _pre(i,a,b) for(int i=(a);i>=(b);--i)
#define all(x) (x).begin(), (x).end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef unsigned long long ULL;
typedef pair<int,int>PII;
typedef pair<double,double>PDD;
const int N=1e6+10,INF=4e18;
int n,m;
int x,y,r,vx,vy,lx,ly,rx,ry;
bool check(int initx,int inity,double x,double y,int op)
{
double now=min({ry-y,y-ly,rx-x,x-lx});
if(op==1)
{
if(x<initx||y<inity)return false;
}
else if(op==2)
{
if(x>initx||y<inity)return false;
}
else if(op==3)
{
if(x>initx||y>inity)return false;
}
else if(x<initx||y>inity)return false;
return now>=r;
}
bool check1(double x,double y)
{
double now=min({ry-y,y-ly,rx-x,x-lx});
return now>=r;
}
bool inside(double x,double y)
{
if(x<=rx&&x>=lx&&y>=ly&&y<=ry)return true;
return false;
}
PDD lineX(PDD p0, PDD p1, PDD p2, PDD p3) {
double A1 = p1.se - p0.se;
double B1 = p0.fi - p1.fi;
double C1 = A1 * p0.fi + B1 * p0.se;
double A2 = p3.se - p2.se;
double B2 = p2.fi - p3.fi;
double C2 = A2 * p2.fi + B2 * p2.se;
double denominator = A1 * B2 - A2 * B1;
return {(B2 * C1 - B1 * C2) / denominator,(A1 * C2 - A2 * C1) / denominator};
}
void solve()
{
cin>>x>>y>>r>>vx>>vy;
cin>>lx>>ly>>rx>>ry;
double midx,midy;
bool bl=false;
if(vx==0)
{
midx=x;
if(vy>0)midy=max((ly+ry)/2.0,y*1.0);
else midy=min((ly+ry)/2.0,y*1.0);
if(check1(midx,midy))bl=true;
}
else if(vy==0)
{
midy=y;
if(vx>0)midx=max((lx+rx)/2.0,x*1.0);
else midx=min((lx+rx)/2.0,x*1.0);
if(check1(midx,midy))bl=true;
}
else
{
int op;
if(vx>0&&vy>0)op=1;
else if(vx<0&&vy>0)op=2;
else if(vx<0&&vy<0)op=3;
else op=4;
int square;
if(ry-ly>rx-lx)
{
square=rx-lx;
PDD x1=lineX({lx,ry-square},{rx,ry},{x,y},{x+vx,y+vy});
if(inside(x1.fi,x1.se))
if(check(x,y,x1.fi,x1.se,op))bl=true;
PDD x2=lineX({lx,ry},{rx,ry-square},{x,y},{x+vx,y+vy});
if(inside(x2.fi,x2.se))
if(check(x,y,x2.fi,x2.se,op))bl=true;
PDD x3=lineX({lx,ly},{rx,ly+square},{x,y},{x+vx,y+vy});
if(inside(x3.fi,x3.se))
if(check(x,y,x3.fi,x3.se,op))bl=true;
PDD x4=lineX({lx,ly+square},{rx,ly},{x,y},{x+vx,y+vy});
if(inside(x4.fi,x4.se))
if(check(x,y,x4.fi,x4.se,op))bl=true;
}
else
{
square=ry-ly;
PDD x1=lineX({lx,ly},{lx+square,ry},{x,y},{x+vx,y+vy});
if(inside(x1.fi,x1.se))
if(check(x,y,x1.fi,x1.se,op))bl=true;
PDD x2=lineX({lx,ry},{lx+square,ly},{x,y},{x+vx,y+vy});
if(inside(x2.fi,x2.se))
if(check(x,y,x2.fi,x2.se,op))bl=true;
PDD x3=lineX({rx-square,ly},{rx,ry},{x,y},{x+vx,y+vy});
if(inside(x3.fi,x3.se))
if(check(x,y,x3.fi,x3.se,op))bl=true;
PDD x4=lineX({rx-square,ry},{rx,ly},{x,y},{x+vx,y+vy});
if(inside(x4.fi,x4.se))
if(check(x,y,x4.fi,x4.se,op))bl=true;
}
// PDD x1=lineX({lx,ly},{rx,ry},{x,y},{x+vx,y+vy});
// if(inside(x1.fi,x1.se))
// if(check(x,y,x1.fi,x1.se,op))bl=true;
// PDD x2=lineX({lx,ry},{rx,ly},{x,y},{x+vx,y+vy});
// if(inside(x2.fi,x2.se))
// if(check(x,y,x2.fi,x2.se,op))bl=true;
PDD x3=lineX({lx,(ly+ry)/2.0},{rx,(ly+ry)/2.0},{x,y},{x+vx,y+vy});
if(inside(x3.fi,x3.se))
if(check(x,y,x3.fi,x3.se,op))bl=true;
PDD x4=lineX({(lx+rx)/2.0,ly},{(lx+rx)/2.0,ry},{x,y},{x+vx,y+vy});
if(inside(x4.fi,x4.se))
if(check(x,y,x4.fi,x4.se,op))bl=true;
if(inside(x,y))
if(check1(x,y))bl=true;
// cout<<x1.fi<<" "<<x1.se<<" "<<x2.fi<<" "<<x2.se<<endl;
}
if(bl)cout<<"Yes"<<'\n';
else cout<<"No"<<'\n';
return ;
}
signed main()
{
IOS;
int T=1;
cin>>T;
while(T--)
solve();
return 0;
}
G - Function Query(补)
题意
思路
用一个等高的01字典树维护每个x,由于每个f(x)要么<=0要么>=0,有点像函数零点,也就是如果我能找到最左的l满足f(x)<=0,最右的r满足f(x)>=0,那么中间一定至少有一个函数零点,这个点可以用二分找,假设mid=l+r>>1,如果f(mid)<=0,那我mid就可以和r配,也就是使得l=mid,直到l+1=r
这个01字典树只需要维护每个节点的最小和最大下标即可
假如二进制下
a=1010110
b=0111000
那么为了使x^a=b,那么每次查询的路线一定是a^b,也就是
x=1101110 (这样才能满足a^x=b)
然后为了使x^a<=b,那么每次b的某一位为1的时候,我让此时x的这一位^1,那么x^a这一位就会=0,这样此时搜到的点就是x<=a的点,这个点维护的最小/大下标就可以统计一下答案
反之为了使x^a<=b,那么每次b的某一位为0的时候,我让此时x的这一位^1,那么x^a这一位就会=1,这样此时搜到的点就是x>=a的点,这个点维护的最小/大下标就可以统计一下答案
代码
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define u1 (u<<1)
#define u2 (u<<1|1)
#define pb push_back
#define pp pop_back()
//#define int long long
#define laile cout<<"laile"<<endl
#define lowbit(x) ((x)&(-x))
#define double long double
#define sf(x) scanf("%lld",&x)
#define sff(x,y) scanf("%lld %lld",&x,&y)
#define sd(x) scanf("%Lf",&x)
#define sdd(x,y) scanf("%Lf %Lf",&x,&y)
#define _for(i,n) for(int i=0;i<(n);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define _pre(i,a,b) for(int i=(a);i>=(b);--i)
#define all(x) (x).begin(), (x).end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef unsigned long long ULL;
typedef pair<int,int>PII;
typedef pair<double,double>PDD;
const int N=9e6+10,INF=0x3f3f3f3f;
int n,m;
int q[N];
int ne[N][2],idx=1;
int maxid[N][2],minid[N][2];
void insert(int now,int id)
{
vector<int>v;
int p=1;
_pre(i,30,0)
{
int t=now>>i&1;
if(!ne[p][t])ne[p][t]=++idx;
maxid[p][t]=max(id,maxid[p][t]);
minid[p][t]=min(id,minid[p][t]);
p=ne[p][t];
}
}
PII queryma(int p,int a,int b)//a^x>=b
{
int ma=0,mi=INF;
bool bl=true;
int ta,tb,t;
_pre(i,30,0)
{
ta=a>>i&1;
tb=b>>i&1;
t=ta^tb;
if(tb==0)ma=max(ma,maxid[p][t^1]),mi=min(mi,minid[p][t^1]);
// cout<<"nowma"<<ma<<" "<<mi<<endl;
if(!ne[p][t])
{
p=ne[p][t];
break;
}
if(i)p=ne[p][t];
}
// cout<<"ma的p="<<p<<" "<<maxid[p][t]<<" "<<minid[p][t]<<endl;
if(p)ma=max(ma,maxid[p][t]),mi=min(mi,minid[p][t]);
return {mi,ma};
}
PII querymi(int p,int a,int b)//a^x<=b
{
int ma=0,mi=INF;
bool bl=true;
int ta,tb,t;
_pre(i,30,0)
{
ta=a>>i&1;
tb=b>>i&1;
t=ta^tb;
if(tb==1)
ma=max(ma,maxid[p][t^1]),mi=min(mi,minid[p][t^1]);
if(!ne[p][t])
{
p=ne[p][t];
break;
}
if(i)p=ne[p][t];
}
if(p)ma=max(ma,maxid[p][t]),mi=min(mi,minid[p][t]);
return {mi,ma};
}
int cal(int x,int a,int b)
{
// cout<<"x="<<x<<" "<<a<<" "<<b<<" "<<((x^a)-b)<<endl;
return (x^a)-b;
}
void solve()
{
memset(maxid,0,sizeof maxid);
memset(minid,0x3f,sizeof minid);
cin>>n>>m;
_rep(i,1,n)
{
cin>>q[i];
insert(q[i],i);
}
while(m--)
{
int a,b;
cin>>a>>b;
PII findma=queryma(1,a,b);
PII findmi=querymi(1,a,b);
// cout<<"计算出"<<findma.fi<<" "<<findma.se<<" "<<findmi.fi<<" "<<findmi.se<<endl;
if(findma.fi<=findmi.se||findmi.fi<=findma.se)
{
int l,r;
if(findma.fi<=findmi.se)l=findma.fi,r=findmi.se;
else l=findmi.fi,r=findma.se;
// cout<<" 初始"<<l<<" "<<r<<" "<<cal(q[l],a,b)<<" "<<cal(q[r],a,b)<<endl;
while(l+1<r)
{
int mid=l+r>>1;
int aa=cal(q[l],a,b);
int bb=cal(q[mid],a,b);
if(aa==0||bb==0||(aa>0&&bb<0)||(aa<0&&bb>0))r=mid;
else l=mid;
}
// cout<<" "<<l<<" "<<r<<" "<<cal(q[l],a,b)<<" "<<cal(q[r],a,b)<<endl;
if(l==n)cout<<n-1<<'\n';
else cout<<l<<'\n';
// cout<<" YES"<<endl;
}
else cout<<"-1"<<'\n';
}
return ;
}
signed main()
{
IOS;
int T=1;
// cin>>T;
while(T--)
solve();
return 0;
}
H - GG and YY's Stone Game
签到
I - Container Scheduling
题意
给定一个大矩形和q次询问,每次询问给出一个小矩形,要求小矩形的x坐标尽可能小,如果放不下就输出-1
思路
手玩一个离谱的矩形可以发现,不管怎么给矩形,最后最优的放置(这里找的是当前需要放置的矩形左下角位置)一定是在所有放置过的矩形的右下角的x的集合和y的集合中取出一个(除了初始状态0,0要额外加入),例如,图中的5放在这个位置是最优的了,可以看到5矩形的左下角是落在了3矩形(右下角)的x和2矩形(右下角)的y上,所以每次放置矩形用两个vector存x和y,由于x要尽可能小,所以每次x加入之后要排序
代码
#include<iostream>
#include<map>
#include<cmath>
#include<string>
#include<vector>
#include<cstring>
#include<algorithm>
#include<unordered_map>
#define pb push_back
#define fi first
#define se second
#define int long long
#define all(x) (x).begin(),(x).end()
#define _for(i, a) for(int i = 0; i < (a); ++i)
#define _rep(i, a, b) for(int i = (a);i <= (b); ++i)
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define u1 (u<<1)
#define u2 (u<<1|1)
//#define endl '\n'
using namespace std;
typedef pair<int,int> PII;
const int INF=0x3f3f3f3f;
const int P=1e9+7;
const int N=1e6+20,M=2*N;
int n,l,h;
struct aa
{
PII ld,ru;
};
vector<aa>now;
bool jiao(PII a,PII b)
{
if(a.fi<b.se&&a.se>b.fi)return true;
if(b.fi<a.se&&b.se>a.fi)return true;
return false;
}
bool suit(aa a)
{
if(a.ru.fi>l||a.ru.se>h)return false;
for(auto i:now)
{
aa b=i;
if(jiao({a.ld.fi,a.ru.fi},{b.ld.fi,b.ru.fi})&&jiao({a.ld.se,a.ru.se},{b.ld.se,b.ru.se}))
{
return false;
}
}
return true;
}
void solve(){
cin>>n>>l>>h;
vector<int> x;
vector<int> y;
x.pb(0);
y.pb(0);
_for(i,n){
int a,b;
cin>>a>>b;
bool bl=false;
_for(i,x.size()){
_for(j,y.size()){
if(suit({{x[i],y[j]},{x[i]+a,y[j]+b}}))
{
bl=true;
now.pb({{x[i],y[j]},{x[i]+a,y[j]+b}});
cout<<x[i]<<" "<<y[j]<<'\n';
x.pb(x[i]+a);
y.pb(y[j]+b);
sort(all(x));
sort(all(y));
break;
}
}
if(bl)break;
}
if(!bl)cout<<"-1\n";
}
}
signed main(){
IOS;
int T=1;
// cin>>T;
_rep(i,1,T){
solve();
}
return 0;
}
L - Beef Tripe in Soup Pot?
签到
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define u1 (u<<1)
#define u2 (u<<1|1)
#define pb push_back
#define pp pop_back()
#define int long long
#define laile cout<<"laile"<<endl
#define lowbit(x) ((x)&(-x))
#define double long double
#define sf(x) scanf("%lld",&x)
#define sff(x,y) scanf("%lld %lld",&x,&y)
#define sd(x) scanf("%Lf",&x)
#define sdd(x,y) scanf("%Lf %Lf",&x,&y)
#define _for(i,n) for(int i=0;i<(n);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define _pre(i,a,b) for(int i=(a);i>=(b);--i)
#define all(x) (x).begin(), (x).end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef unsigned long long ULL;
typedef pair<int,int>PII;
const int N=1e6+10,INF=4e18;
int n,m;
vector<PII>a,b;
void solve()
{
cin>>n;
_rep(i,1,n)
{
int x,y,c,d;
cin>>x>>y>>c>>d;
if(c+d==2)
{
if(x<y)a.pb({x,i});
else b.pb({y,i});
}
else if(c)a.pb({x,i});
else if(d)b.pb({y,i});
}
sort(all(a));
sort(all(b));
cout<<(int)a.size();
for(auto i:a)cout<<" "<<i.se;
cout<<'\n';
cout<<(int)b.size();
for(auto i:b)cout<<" "<<i.se;
return ;
}
signed main()
{
IOS;
int T=1;
// cin>>T;
while(T--)
solve();
return 0;
}