1011
Segment Tree with Pruning
题意:限制区间长度为\(k\),并给定建树区间为 \((1-n)\),询问该线段树会产生几个节点。
是一道搜索题(刚开始还以为是结论题)。加入记忆化搜索优化时间复杂度,对每一个子树仅打开一次。因为线段树本身仅可能会有\(logN\)个长度不同的区间,所以时间复杂度得以控制在\(O(logNloglogN)\)。
标程
#include<cstdio>
#include<map>
using namespace std;
typedef long long ll;
int Case;ll n,k;map<ll,ll>T;
ll build(ll n){
if(T.find(n)!=T.end())return T[n];
if(n<=k)return T[n]=1;
return T[n]=build(n/2)+build(n-n/2)+1;
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%lld%lld",&n,&k);
T.clear();
printf("%lld\n",build(n));
}
return 0;
}
1007
Photoshop Layers

题意:定义一个图层有两种混合模式,模式\(1\)为直接覆盖,模式\(2\)线性减淡。给定\(n\)个图层信息,并有\(q\)个询问一个区间内\((l-r)\)若干个图层所形成的图像。
预处理出每一层往右数的第一个模式\(1\)图层,并用前缀和求得区间和,答案和\(255\)比较。
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
struct layer
{
int mode;
string col;
}p[MAXN];
struct rgb
{
int r,g,b;
}rb[MAXN];
int pref[MAXN];rgb pe[MAXN];
inline rgb trans(int s1){
rgb ans;
ans.b=s1&255;//取开始两位数
s1>>=8;//相当于十进制数的膜10
ans.g=s1&255;
s1>>=8;
ans.r=s1;
return ans;
}
void solve(int index1,int index2){
int R=min(pe[index2].r-pe[index1-1].r,255);
int G=min(pe[index2].g-pe[index1-1].g,255);
int B=min(pe[index2].b-pe[index1-1].b,255);
printf("%02X%02X%02X\n",R,G,B);//十六进制大写字母输出
}
int main(){
int T,n,q;
cin>>T;
while (T--)
{
cin>>n>>q;
for(int i=1;i<=n;i++){
int m;int s;
// cin>>m>>s;
scanf("%d%X",&m,&s);//十六进制读入
p[i].mode=m,p[i].col=s;
rb[i]=trans(s);
}
int pr=1;
for(int i=1;i<=n;i++){
if(p[i].mode==1)pr=i;
pref[i]=pr;
}
rb[0].g=rb[0].b=rb[0].r=0;
rgb sk=rb[1];
for(int i=1;i<=n;i++){
pe[i].r=sk.r,pe[i].g=sk.g,pe[i].b=sk.b;
sk.r+=rb[i+1].r,sk.g+=rb[i+1].g,sk.b+=rb[i+1].b;
}
while (q--)
{
int l,r;
scanf("%d%d",&l,&r);
int index=pref[r];
if(index<l) solve(l,r);
else solve(index,r);
}
}
system("pause");
return 0;
}
1004
Game on Plane

策略:一个比较简单的博弈,由题意可知Bob的最优策略一定是避开斜率出现次数最多的那些直线。Alice对此也心知肚明,因此会最小化斜率出现次数的最大值,所以不断从每种斜率的直线中各选一种即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const ll INF=1e10;
int cnt[110010];
map<ld,ll>p;
int main(){
int T;
cin>>T;
while (T--)
{
memset(cnt,0,sizeof(cnt));
p.clear();
int n;
cin>>n;
int nub=n;
while (nub--)
{
ll a,b,c,d;
ld K;
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
if(a==c)K=INF;
else K=(d-b)*1.0/(c-a);
p[K]++;//这里我使用了一个map来记录所有斜率的出现次数
}
int nt=p.size();
for (auto iter = p.begin(); iter!=p.end(); ++iter)
cnt[iter->second]++;//在cnt数组中写入map中的数据,即出现一次数量,
//出现两次数量......
for (int i = 100010; i >=1 ; i--)
cnt[i-1]+=cnt[i]; // 求一个后缀和
int nid=1,ans=-1,k=1;
for (int i = 1; i <= n; i++,k++)
{
if(k<=cnt[nid]) ans++;
else{
k=k-cnt[nid];
nid++;
}
printf("%d\n",ans);
}
}
system("pause");
return 0;
}
posted on
浙公网安备 33010602011771号