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

image
题意:定义一个图层有两种混合模式,模式\(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 2021-08-09 22:03  Stuart_Assassins  阅读(36)  评论(0)    收藏  举报