现场只过了4题 险些没名额,1,6,7,8
其中7,8,我敲,1参与思考,6:zsben敲
太菜了,之前一直温水煮青蛙,今天发现差距了,中期题不会做,只会做思维水题。
补题情况:
---队友过的 且未补题
Ο 自己过的或赛后补题
题号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | |
状态 | Ο | Ο | . | . | . | --- | Ο | Ο | . | . |
1001:水题,(a^c )& ( b^c) 最小,
按位看
a:1 b:1 c这一位必须是1,才能让这一位变0.
a:1 ,b:0或a:0, b:1或a:0 b:0这样c任取,那我们取C==0
就相当于a&b.但题目说C必须正整数。所以当c取0时 取1即可
代码略
1002:
一道很有思维度的简单线段树。
比赛的时候一直想主席树套树状数组转在线,又想并查集,越想越复杂。
其实仔细思考可以发现,l始终是1,只有r发生变化。
询问的是第一个权值大于k,且不在1-->r 之间的数。
我们看到数据范围,1<=n,a[i],k<=1e5,而加的数是1e6,
把一个数加上1e6相当于在权值线段树里把他删去。自然而然的想到建一棵权值线段树。
比赛的时候想到了这里,然后怎么询问第一个权值大于k,且不在1-->r之间的数不会弄。
其实我们权值线段树稍微变一下,每个结点维护这个数出现的位置。
还是按权值去建树。
比如样例:
4 3 1 2 5 -->3 4 2 1 5.
数字’1‘的位置是3,所以l==r==1时,st[o]存的是。
这样一变化,问题就转化成了:求整体区间内:第一个位置大于r且权值大于等于k的数。
这样就变成了一个很基础的权值线段树的处理了。
找到第一个位置后,直接返回,这样的复杂度是找第一个位置的复杂度:也就是logn。
//KX
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int M= 1e5+7;
int st[M<<2],pos[M],a[M],qz[M];
int n,m,sz=100000+7,now;
bool f;
#define ls o*2
#define rs o*2+1
void bd(int o,int l,int r)
{
if(l==r)
{
st[o]=pos[l];
return ;
}
int m=(l+r)/2;
bd(ls,l,m);
bd(rs,m+1,r);
st[o]=max(st[ls],st[rs]);
}
void up(int o,int l,int r,int x)
{
if(l==r)
{
st[o]=sz;
pos[l]=sz;
return ;
}
int m=(l+r)/2;
if(x<=m)up(ls,l,m,x);
else up(rs,m+1,r,x);
st[o]=max(st[ls],st[rs]);
}
void qu(int o,int l,int r,int y,int k)
{
//printf("%d %d %d y:%d k:%d st[ls]: %d st[rs]:%d\n",l,r,st[o],y,k,st[ls],st[rs]);
if(f||r<k)return ;
//if(l<k)return ;
if(l==r)
{
now=l;
f=true;
return ;
}
int m=(l+r)/2;
if(st[ls]>y) qu(ls,l,m,y,k);
if(st[rs]>y) qu(rs,m+1,r,y,k);
}
int main()
{
int t,las=0;
cin>>t;
while(t--)
{
las=0;
scanf("%d%d",&n,&m);
for(int i=1;i<M*2;i++)pos[i]=sz;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
pos[a[i]]=i;
qz[i]=a[i];
}
bd(1,1,sz);
for(int i=1;i<=m;i++)
{
int c,y,k;
scanf("%d",&c);
if(c==1)
{
scanf("%d",&y);
y=y^las;
// printf("----%d\n",qz[y])
up(1,1,sz,qz[y]);
}
else
{
scanf("%d%d",&y,&k);
y=y^las;k=k^las;
f=false;
qu(1,1,sz,y,k);
printf("%d\n",now);
las=now;
}
}
}
return 0;
}
/*
3
5 9
4 3 1 2 5
2 1 1
2 3 3
2 3 2
2 3 1
2 4 1
2 5 1
*/
1006,倒着想即可。
1007,模拟
//KX
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int M= 1e5+7;
int a[M];
char s[1100][1100];
int main()
{
int t;
s[1][1]='C';
s[1][2]='C';
s[2][1]='P';
s[2][2]='C';
for(int l=1;l<=9;l++)
{
int now=1<<(l+1);
int pre=now/2;
for(int i=1;i<=pre;i++)
for(int j=pre+1;j<=now;j++)
{
s[i][j]=s[i][j-pre];
s[i+pre][j]=s[i][j-pre];
if(s[i][j-pre]=='C')
s[i+pre][j-pre]='P';
else
s[i+pre][j-pre]='C';
}
}
cin>>t;
while(t--)
{
int d;
scanf("%d",&d);
int w=1<<d;
for(int i=1;i<=w;i++)
for(int j=1;j<=w;j++)
{
printf("%c",s[i][j]);
if(j==w)puts("");
}
}
return 0;
}
1008,
我搞完1007后,zsben1006过了,然后先过了1006,去想1002自闭。。看1008过的人多了,就看了下,
直接就有思路了:首先,
最少的时间肯定时先抓一条鱼,然后加上炖鱼的时间,在炖鱼的时间取抓鱼。
但是会有去抓鱼但炖鱼好了的情况。
我们让这种浪费的时间最少即可。
先让所有炖鱼的时间%k,然后从大到小排序(其实没必要优先队列),这样肯定是抓鱼时间浪费最少的排序,抓满n条即可。
//KX
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
#define F first
#define S second
const ll INF64=8000000000000000000LL;
const int INF=0x3f3f3f3f;
const ld PI=acos(-1);
const ld eps=1e-9;
const ll MOD=ll(1e9+7);
const int M = 1e5 + 10;
void modup(int&x){if(x>=MOD)x-=MOD;}
ll a[M];
priority_queue<ll> q;
int main()
{
int t;
cin>>t;
while(t--)
{
ll n,k;
scanf("%lld%lld",&n,&k);
ll w=0;
ll ans=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
ans+=a[i];
w+=a[i]/k;
ll zz=a[i]%k;
q.push(zz);
}
// puts("ok");
ans+=k;
while(w<n-1)
{
ll now=q.top();
q.pop();
ans+=k-now;
w++;
}
printf("%lld\n",ans);
while(!q.empty())
{
q.pop();
}
}
return 0;
}