HDU多校3

HDU多校3

传送门

1004.Game on Plane

思路:

将斜率存入pair后,将线段分成不同种类,之后按不同种类依次选择线段。

交点出为线段总数减去当前存在最多线段数

具体实现看代码。

#include <iostream>
#include <map>
#include <queue>
#define bug cout<<"???\n";
using namespace std;
const int N=1e5+7;
typedef long long ll;
typedef pair<int,int> pll;
int T,n,tot,sz[N],cnt[N];
queue <int> q,sa;
map<pll,int> ma;
void init(){
    for(int i=0;i<=n+1;i++) sz[i]=cnt[i]=0;
    while(!q.empty()) q.pop();
    while(!sa.empty()) sa.pop();
    ma.clear();
    tot=0;
}
int gcd(int x,int y){return y==0? x:gcd(y,x%y);}
void add(int x1,int y1,int x2,int y2){
    int nx=x2-x1,ny=y2-y1;
    int gd=gcd(nx,ny);;
    nx=nx/gd,ny=ny/gd;
    if(1ll*nx*ny<0){
        if(ny<0) nx=-nx,ny=-ny;
    }else if(nx==0){
        nx=0,ny=1;
    }else if(ny==0){
        nx=0,ny=0;
    }
    if(!ma.count(pll(nx,ny))) ma[pll(nx,ny)]=++tot;
    sz[ma[pll(nx,ny)]]++;
}
void solve(){
    scanf("%d",&n);
    init();
    for(int i=1;i<=n;i++){
        int x1,y1,x2,y2;
        scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
        add(x1,y1,x2,y2);
    }
    for(int i=1;i<=tot;i++){
        sz[i]--;q.push(i);sa.push(i);
    }
    while(!q.empty()){
        int p=q.front();q.pop();
        if(sz[p]-1>=0){
            sz[p]--;q.push(p);sa.push(p);
        }
    }
    int all=0;
    for(int i=1;i<=n;i++){
        int p=sa.front();sa.pop();
        all++;cnt[p]++;
        printf("%d\n",all-cnt[p]);
    }
}
int main(){
    scanf("%d",&T);
    while(T--) solve();

}

1007.Photoshop Layers

思路:

处理前缀和,记录当前位置在那个位置将会重置,然后处理十六进制。

#include <iostream>
#define fi first
#define se second
using namespace std;
typedef pair <char,char> pll;
const int N=1e5+7;
int t,n,m;
int op[N],ma[N],f[N];
char cat[N];
char a[N][10];
int s1[N],s2[N],s3[N];
void init(){
    ma['1']=1;ma['2']=2;ma['3']=3;ma['4']=4;ma['5']=5;ma['6']=6;ma['7']=7;ma['8']=8;
    ma['9']=9;ma['A']=10;ma['B']=11;ma['C']=12;ma['D']=13;ma['E']=14;ma['F']=15;ma['0']=0;
    cat[1]='1';cat[2]='2';cat[3]='3';cat[4]='4';cat[5]='5';cat[6]='6';cat[7]='7';cat[8]='8';
    cat[9]='9';cat[10]='A';cat[11]='B';cat[12]='C';cat[13]='D';cat[14]='E';cat[15]='F';cat[0]='0';
}
pll print(int num){
    return pll(cat[num/16],cat[num%16]);
}
int add(int num1,char ch1,char ch2){
    int num2=ma[ch1]*16+ma[ch2];
    return num1+num2;
}

int main(){
    scanf("%d",&t);
    init();
    while(t--){
        scanf("%d %d",&n,&m);

        for(int i=1;i<=n;i++){
            scanf("%d",&op[i]);
            scanf("%s",a[i]+1);
        }
        for(int i=1;i<=n;i++){
            if(op[i]==1){
                s1[i]=add(0,a[i][1],a[i][2]);
                s2[i]=add(0,a[i][3],a[i][4]);
                s3[i]=add(0,a[i][5],a[i][6]);
            }else{
                s1[i]=add(s1[i-1],a[i][1],a[i][2]);
                s2[i]=add(s2[i-1],a[i][3],a[i][4]);
                s3[i]=add(s3[i-1],a[i][5],a[i][6]);
            }
        }
        for(int i=1;i<=n;i++){
            if(op[i]==1){
                f[i]=i;
            }else{
                f[i]=f[i-1];
            }
        }
        while(m--){
            int l,r;
            scanf("%d %d",&l,&r);
            int num1,num2,num3;
            if(f[r]>l-1){
                num1=s1[r],num2=s2[r],num3=s3[r];
            }else{
                num1=s1[r]-s1[l-1],num2=s2[r]-s2[l-1],num3=s3[r]-s3[l-1];
            }
            num1=min(255,num1),num2=min(255,num2),num3=min(255,num3);
            pll it1=print(num1),it2=print(num2),it3=print(num3);          printf("%c%c%c%c%c%c\n",it1.fi,it1.se,it2.fi,it2.se,it3.fi,it3.se);
        }
    }

}

1101.Segment Tree with Pruning

思路

记忆化搜索即可,别看数据挺大,状态其实也不多,用map存dp

#include <iostream>
#include <map>
using namespace std;
typedef long long ll;
int T;
map <ll,ll> dp;
ll n,k;
ll dfs(ll s){
    ll ans=0;
    if(s<=k) return 1;
    if(dp[s]) return dp[s];
    if(s&1) ans+=dfs(s/2)+dfs(s/2+1)+1;
    else ans+=2*dfs(s/2)+1;
    return dp[s]=ans;
}
void solve(){
    cin>>n>>k;
    dp.clear();
    cout<<dfs(n)<<"\n";
}
int main(){
    cin>>T;
    while(T--) solve();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值