目录
A.Cactus Draw
根据深度建点,队友代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
vector<int>t[1005];
pair<int,int> ans[1005];
int h[1005];
void dfs(int u,int fa,int dep)
{
ans[u]=make_pair(dep,h[dep]++);
for(int i=0;i<t[u].size();i++)
{
int v=t[u][i];
if(v==fa)continue;
dfs(v,u,dep+1);
}
}
int main()
{
scanf("%d%d",&n,&m);
int u,v;
fill(h+1,h+1005,1);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
t[u].push_back(v);
t[v].push_back(u);
}
dfs(1,0,1);
for(int i=1;i<=n;i++)
printf("%d %d\n",ans[i].first,ans[i].second);
return 0;
}
C.Division
从大到小贪心操作就行了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2e5+5;
ll a[N];
int main()
{
ll n,k,x;
scanf("%lld%lld",&n,&k);
priority_queue<ll>q;
for(ll i=1;i<=n;i++){
scanf("%lld",&x);
q.push(x);
}
ll ans=0,cnt=0;
while(1){
ll t=q.top();q.pop();
if(t==0) break;
q.push(t/2);
cnt++;
if(cnt>=k) break;
}
while(!q.empty()){
ans+=q.top();q.pop();
}
printf("%lld\n",ans);
return 0;
}
D.Doppelblock
暴力搜索,加一些减枝。如果两个X内的数之和不是要求的,剪掉;如果还没放过X,但剩下的数字没法达到要求了,剪掉。
还可以预处理X的位置,没有写。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=10;
int row[N][N],col[N][N];
int r[N],c[N],tr[N],tc[N];
int t,n,tot;
char pr[N][N];
bool dfs(int x,int y){
if(x>n) return true;
for(int i=1;i<=n-2;i++){
if(row[x][i]) continue;
if(col[y][i]) continue;
if(row[x][0]==0){
if(tr[x]+i+r[x]>tot) continue;
}
else if(row[x][0]==1){
if(tr[x]+i>r[x]) continue;
}
if(col[y][0]==0){
if(tc[y]+i+c[y]>tot) continue;
}
else if(col[y][0]==1){
if(tc[y]+i>c[y]) continue;
}
pr[x][y]='0'+i;
row[x][i]=true;col[y][i]=true;
tr[x]+=i;tc[y]+=i;
if(y==n){
if(dfs(x+1,1)) return true;
}
else{
if(dfs(x,y+1)) return true;
}
row[x][i]=false;col[y][i]=false;
tr[x]-=i;tc[y]-=i;
}
if(row[x][0]==2) return false;
if(col[y][0]==2) return false;
if(row[x][0]==1&&tr[x]!=r[x]) return false;
if(col[y][0]==1&&tc[y]!=c[y]) return false;
pr[x][y]='X';
row[x][0]++;col[y][0]++;
int ttr=tr[x],ttc=tc[y];
tr[x]=tc[y]=0;
if(y==n){
if(dfs(x+1,1)) return true;
}
else{
if(dfs(x,y+1)) return true;
}
row[x][0]--;col[y][0]--;
tr[x]=ttr;tc[y]=ttc;
return false;
}
void init(){
tot=(n-1)*(n-2)/2;
for(int i=0;i<=n;i++){
r[i]=c[i]=tr[i]=tc[i]=0;
for(int j=0;j<=n;j++){
row[i][j]=col[i][j]=0;
}
}
}
int main()
{
scanf("%d",&t);
while(t--){
scanf("%d",&n);
init();
for(int i=1;i<=n;i++) scanf("%d",&r[i]);
for(int i=1;i<=n;i++) scanf("%d",&c[i]);
dfs(1,1);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
printf("%c",pr[i][j]);
}
printf("\n");
}
printf("\n");
}
return 0;
}
F.Kropki
表示第
位,状态为
,最后一位放
,然后按题意做即可。注意,第一维不能舍去。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=5e4+7;
char st[50];
int dp[50][N][50];
int num[N];
int sum[50][N];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<(1<<n);i++)
num[i]=num[i&(i-1)]+1;
scanf("%s",st+1);
for(int i=1;i<=n;i++){
dp[1][1<<(i-1)][i]=1;
sum[1][1<<(i-1)]=1;
}
for(int i=2;i<=n;i++){
for(int s=0;s<(1<<n);s++){
if(num[s]!=i) continue;
for(int k=1;k<=n;k++){
if(s&(1<<(k-1))){
int ss=s-(1<<(k-1));
if(st[i-1]=='0'){
dp[i][s][k]=sum[i-1][ss];
if(k%2==0){
int tmp=k/2;
dp[i][s][k]=(dp[i][s][k]-dp[i-1][ss][tmp]+mod)%mod;
}
if(k*2<=n){
int tmp=k*2;
dp[i][s][k]=(dp[i][s][k]-dp[i-1][ss][tmp]+mod)%mod;
}
}
else{
dp[i][s][k]=0;
if(k%2==0){
int tmp=k/2;
dp[i][s][k]=(dp[i][s][k]+dp[i-1][ss][tmp])%mod;
}
if(k*2<=n){
int tmp=k*2;
dp[i][s][k]=(dp[i][s][k]+dp[i-1][ss][tmp])%mod;
}
}
sum[i][s]=(sum[i][s]+dp[i][s][k])%mod;
}
}
}
}
printf("%d\n",sum[n][(1<<n)-1]);
}
I.Sorting
因为x是固定的,所以小于等于x的数字相对顺序不会改变,大于x的数字相对顺序也不会改变。把前者看成0,后者看成1,这样就构造成了一个01序列。然后把原先的数字分开按照0和1分开存储前缀和。
- 对于修改操作,就是查询这段区间有多少个0和1,然后把左右边赋值成0或1.
- 对于查询操作,查询前缀有多少个1来确定询问区间的1的所在位置,并用前缀和来计算答案,0也同理。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+7;
int n,q,x,tmp;
ll sum0[N],sum1[N];
int t0,t1;
int t[N<<2],lz[N<<2];
void bd(int rt,int l,int r){
lz[rt]=-1;
if(l==r){
scanf("%d",&tmp);
if(tmp<=x){
t[rt]=0;t0++;
sum0[t0]=tmp+sum0[t0-1];
}
else{
t[rt]=1;t1++;
sum1[t1]=tmp+sum1[t1-1];
}
return;
}
int m=l+r>>1;
bd(rt<<1,l,m);
bd(rt<<1|1,m+1,r);
t[rt]=t[rt<<1]+t[rt<<1|1];
}
void pd(int rt,int l,int r){
if(~lz[rt]){
int m=l+r>>1;
lz[rt<<1]=lz[rt<<1|1]=lz[rt];
t[rt<<1]=lz[rt]*(m-l+1);
t[rt<<1|1]=lz[rt]*(r-m);
lz[rt]=-1;
}
}
void upd(int rt,int l,int r,int L,int R,int val){
if(L<=l&&r<=R){
t[rt]=(r-l+1)*val;
lz[rt]=val;
return;
}
pd(rt,l,r);
int m=l+r>>1;
if(L<=m) upd(rt<<1,l,m,L,R,val);
if(m<R) upd(rt<<1|1,m+1,r,L,R,val);
t[rt]=t[rt<<1]+t[rt<<1|1];
}
int que(int rt,int l,int r,int L,int R){
if(L<=l&&r<=R) return t[rt];
pd(rt,l,r);
int m=l+r>>1,res=0;
if(L<=m) res+=que(rt<<1,l,m,L,R);
if(m<R) res+=que(rt<<1|1,m+1,r,L,R);
return res;
}
int main()
{
scanf("%d%d%d",&n,&q,&x);
bd(1,1,n);
while(q--){
int t,l,r;
scanf("%d%d%d",&t,&l,&r);
if(t==1){
int nr=que(1,1,n,1,r),nl;
if(l>1) nl=que(1,1,n,1,l-1);
else nl=0;
ll ans=sum1[nr]-sum1[nl];
ans+=sum0[r-nr]-sum0[l-1-nl];
printf("%lld\n",ans);
}
else if(t==2){
int num=r-l+1-que(1,1,n,l,r);
upd(1,1,n,l,l+num-1,0);
upd(1,1,n,l+num,r,1);
}
else{
int num=que(1,1,n,l,r);
upd(1,1,n,l,l+num-1,1);
upd(1,1,n,l+num,r,0);
}
}
return 0;
}
J.Special Judge
板子加细节判断,队友代码
#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define fi first
#define se second
#define pb push_back
typedef double db;
const db eps=1e-6;
const db pi=acos(-1);
int sign(db k){
if (k>eps) return 1; else if (k<-eps) return -1; return 0;
}
int cmp(db k1,db k2){return sign(k1-k2);}
int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内
struct point{
db x,y;
point(){}
point(int x,int y){this->x=(db)x;this->y=(db)y;}
point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
point operator * (db k1) const{return (point){x*k1,y*k1};}
point operator / (db k1) const{return (point){x/k1,y/k1};}
int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
// 逆时针旋转
point turn(db k1){return (point){x*cos(k1)-y*sin(k1),x*sin(k1)+y*cos(k1)};}
point turn90(){return (point){-y,x};}
bool operator < (const point k1) const{
int a=cmp(x,k1.x);
if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
}
db abs(){return sqrt(x*x+y*y);}
db abs2(){return x*x+y*y;}
db dis(point k1){return ((*this)-k1).abs();}
point unit(){db w=abs(); return (point){x/w,y/w};}
void scan(){double k1,k2; scanf("%lf%lf",&k1,&k2); x=k1; y=k2;}
void print(){printf("%.11lf %.11lf\n",x,y);}
db getw(){return atan2(y,x);}
point getdel(){if (sign(x)==-1||(sign(x)==0&&sign(y)==-1)) return (*this)*(-1); else return (*this);}
int getP() const{return sign(y)==1||(sign(y)==0&&sign(x)==-1);}
};
int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);}
db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
int intersect(db l1,db r1,db l2,db r2){
if (l1>r1) swap(l1,r1); if (l2>r2) swap(l2,r2); return cmp(r1,l2)!=-1&&cmp(r2,l1)!=-1;
}
int checkSS(point k1,point k2,point k3,point k4){
return intersect(k1.x,k2.x,k3.x,k4.x)&&intersect(k1.y,k2.y,k3.y,k4.y)&&
sign(cross(k3-k1,k4-k1))*sign(cross(k3-k2,k4-k2))<=0&&
sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<=0;
}
int onS(point k1,point k2,point q){return inmid(k1,k2,q)&&sign(cross(k1-q,k2-k1))==0;}
map<int,point>mm;
struct node
{
int u,v;
int nxt;
}edge[2005];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d",&edge[i].u,&edge[i].v);
int x,y;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
mm[i]=point(x,y);
}
int ans=0;
for(int i=1;i<m;i++)
{
for(int j=i+1;j<=m;j++)
{
point p1=mm[edge[i].u],p2=mm[edge[i].v],p3=mm[edge[j].u],p4=mm[edge[j].v];
int tp=checkSS(p1,p2,p3,p4);
if(tp==0)continue;
else if(((p1==p3||p1==p4)&&onS(p3,p4,p2))||((p2==p4||p2==p3)&&onS(p3,p4,p1))||((p3==p1||p3==p2)&&onS(p1,p2,p4))||((p4==p1||p4==p2)&&onS(p1,p2,p3)));
else if(p1==p3||p1==p4||p2==p3||p2==p4)continue;
ans++;
}
}
printf("%d\n",ans);
}