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();
}