标签:void 最大 class clu space floor string end style
咕的太多了,赶紧补补。
前面的就写写题解,最近的再写总结。
模拟,我采取的方法是记录方向和尾部节点。
但是如果使用$vector$记录路径最后$clear$或是直接用$map$会好一些。
我用了一个二维数组,于是T掉了。
后来考完后把数组开小后AC
没人需要代码吧……
还是放一个:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define N 601
#define isv(i,j) visn[(i)+N][(j)+N]
using namespace std;
int visn[2*N][2*N],ans=0;
vector<pair<int,int> >poss;
struct BLOCK{
int edx,edy,dir,len;//dir=0(N),1(S),2(W),3(E),-1(U)
void getpos(){
poss.clear();
switch(dir){
case 0://N↑
for(int i=0;i<len;i++)
poss.push_back(make_pair(edx,edy+i));
break;
case 1://S↓
for(int i=0;i<len;i++)
poss.push_back(make_pair(edx,edy-i));
break;
case 2://W←
for(int i=0;i<len;i++)
poss.push_back(make_pair(edx-i,edy));
break;
case 3://E→
for(int i=0;i<len;i++)
poss.push_back(make_pair(edx+i,edy));
break;
default:poss.push_back(make_pair(edx,edy));
}
}
void updatevis(){
switch(dir){
case 0://N↑
for(int i=0;i<len;i++)
isv(edx,edy+i)++;
break;
case 1://S↓
for(int i=0;i<len;i++)
isv(edx,edy-i)++;
break;
case 2://W←
for(int i=0;i<len;i++)
isv(edx-i,edy)++;
break;
case 3://E→
for(int i=0;i<len;i++)
isv(edx+i,edy)++;
break;
default:isv(edx,edy)++;
}
}
void clear(){
this->edx=this->edy=0;
this->dir=-1;
this->updatevis();
}
void move(const char mq){
switch(mq){
case ‘N‘://0↑
if(this->dir==-1){
this->edy++;
this->dir=0;
}
else if(this->dir==2 || this->dir==3)//W E
this->edy++;
else{
if(this->dir==0)//N
this->edy+=this->len;
else//S
this->edy++;
this->dir=-1;//Up
}
break;
case ‘S‘://1↓
if(this->dir==-1){
this->edy--;
this->dir=1;
}
else if(this->dir==2 || this->dir==3)//W E
this->edy--;
else{
if(this->dir==0)//N
this->edy--;
else//S
this->edy-=this->len;
this->dir=-1;//Up
}
break;
case ‘W‘://2←
if(this->dir==-1){
this->edx--;
this->dir=2;
}
else if(this->dir==0 || this->dir==1)//N S
this->edx--;
else{
if(this->dir==2)//W
this->edx-=this->len;
else//E
this->edx--;
this->dir=-1;
}
break;
case ‘E‘://3→
if(this->dir==-1){
this->edx++;
this->dir=3;
}
else if(this->dir==0 || this->dir==1)//N S
this->edx++;
else{
if(this->dir==3)//E
this->edx+=this->len;
else//W
this->edx++;
this->dir=-1;
}
break;
default:puts("Error A Wrong Move");
}
this->updatevis();
}
void pour(){
cout<<"("<<this->edx<<","<<this->edy<<")";
switch(this->dir){
case -1:
puts("?");
break;
case 0://N
puts("↑");
break;
case 1:
puts("↓");
break;
case 2:
puts("←");
break;
case 3:
puts("→");
break;
default:
puts("A Error In \‘dir\‘");
}
}
}bl;
int cn;
char st[N];
int main(){
// freopen("block.in" ,"r",stdin);
// freopen("block.out","w",stdout);
int T;
cin>>T;
while(T--){
memset(visn,0,sizeof visn);
memset(st,0,sizeof st);
bl.clear();
ans=0;
scanf("%d%s",&bl.len,st+1);
for(int i=1;st[i]!=0;i++)
bl.move(st[i]);//bl.pour();
bl.getpos();
sort(poss.begin(),poss.end());
for(int i=0;i<poss.size();i++)
printf("%d ",poss[i].first);
puts("");
for(int i=0;i<poss.size();i++)
printf("%d ",poss[i].second);
puts("");
for(int i=-600;i<=600;i++)
for(int j=-600;j<=600;j++)
ans=max(ans,isv(i,j));
printf("%d\n",ans);
}
}
毒瘤数学题,不会……咕咕咕。
新思路:把一段操作压成一个$hash$值
或者靠这个题的特性,维护值域区间。
于是线段树区间乘,区间加。
代码撂着:
#include <iostream>
#include <cstring>
#include <cstdio>
#define N 222222
#define LL long long
using namespace std;
const int Mod=1995667591,Upbit=333667;
struct XDS{
int l,r;
LL add,muilt;
#define lc(k) ((k)<<1)
#define rc(k) (((k)<<1)|1)
}rt[4*N];
int dn,cn,clt;
LL clhs=0;
void build(int k,int l,int r){//cout<<k<<" + "<<l<<" + "<<r<<endl;
rt[k].l=l,rt[k].r=r;
rt[k].add=0;
rt[k].muilt=1;
if(l==r)
return ;
int mid=(l+r)>>1;
build(lc(k),l ,mid);
build(rc(k),mid+1,r);
}
void downlazy(int k){
if(rt[k].l!=rt[k].r){
if(rt[k].muilt!=1){
rt[lc(k)].muilt=(rt[lc(k)].muilt*rt[k].muilt)%Mod;
rt[rc(k)].muilt=(rt[rc(k)].muilt*rt[k].muilt)%Mod;
rt[lc(k)].add =(rt[lc(k)].add *rt[k].muilt)%Mod;
rt[rc(k)].add =(rt[rc(k)].add *rt[k].muilt)%Mod;
rt[k].muilt=1;
}
if(rt[k].add){
rt[lc(k)].add=(rt[lc(k)].add+rt[k].add)%Mod;
rt[rc(k)].add=(rt[rc(k)].add+rt[k].add)%Mod;
rt[k].add=0;
}
}
}
void add(int k,int l,int r,LL v){//cout<<"-----------------------------------------------------\nAdd:"<<k<<endl <<"RTL:"<<rt[k].l<<endl <<"RTR:"<<rt[k].r<<endl <<"QEL:"<<l<<endl <<"QER:"<<r<<endl <<"QRV:"<<v<<endl;
if(l<=rt[k].l && rt[k].r<=r){
rt[k].add=(v+rt[k].add)%Mod;
return ;
}
if(rt[k].l==rt[k].r)return ;
downlazy(k);
int mid=(rt[k].l+rt[k].r)>>1;
if(l<=mid)
add(lc(k),l,r,v);
if(r>mid)
add(rc(k),l,r,v);
}
void muilt(int k,int l,int r,LL v){//cout<<"===================================================\nMuilt:"<<k<<endl <<"RTL:"<<rt[k].l<<endl <<"RTR:"<<rt[k].r<<endl <<"QEL:"<<l<<endl <<"QER:"<<r<<endl <<"QRV:"<<v<<endl;
if(l<=rt[k].l && rt[k].r<=r){
rt[k].add =(v*rt[k].add)%Mod;
rt[k].muilt=(v*rt[k].muilt)%Mod;
return ;
}
if(rt[k].l==rt[k].r)return ;
downlazy(k);
int mid=(rt[k].l+rt[k].r)>>1;
if(l<=mid)
muilt(lc(k),l,r,v);
if(r>mid)
muilt(rc(k),l,r,v);
}
int getans(int k){
if(rt[k].l==rt[k].r){
//cout<<k<<"----"<<rt[k].add<<"("<<clhs<<")"<<endl;
return rt[k].add==clhs;
}
downlazy(k);
return getans(lc(k))+getans(rc(k));
}
int main(){
int a,b,c;
scanf("%d%d%d",&dn,&clt,&cn);
build(1,1,dn);
for(LL i=1;i<=clt;i++)
clhs=((clhs*Upbit)+i)%Mod;
for(int i=1;i<=cn;i++){
scanf("%d%d%d",&a,&b,&c);
muilt(1,a,b,Upbit);
add (1,a,b,c);
}
printf("%d\n",getans(1));
}
Codeforces & AtCoder
<题目链接>
题目被翻译了,还被改名了 ??
不管了。
这是虎的加强版。
贪心。在图上DFS,形成一棵搜索树。
那么可以把边分为鸡肋几类
不是通向父节点的两两配对,
通向父节点的分类讨论,和下面剩下的配,其次贡献给父节点
这样贪心的结果是可以保证的,最多只有根节点有一条边被浪费。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define M 222222
#define N 222222
using namespace std;
struct SR{
int next,t;
bool is_des,is_tr;
SR(){next=t=is_des=is_tr=0;}
}rs[2*M];
int pn,
edn,
cnt=0,
fl[N],
deg[N];
bool is_v[N],
usdfa[N];
struct ANS{
int f,m,t;
ANS(int a,int b,int c):f(a),m(b),t(c){}
};
vector<ANS>ans;
void add(int f,int t){
rs[cnt].t=t;
rs[cnt].next=fl[f];
fl[f]=cnt++;
}
void dfs(int k,int pre,int pp){//cout<<k<<"<-"<<pp<<endl;
is_v[k]=1;
int ls=0,lstid;
if(pre!=-1)rs[pre].is_tr=rs[pre^1].is_tr=1;
for(int i=fl[k];i!=-1;i=rs[i].next){
int t=rs[i].t;
if(rs[i].is_des || t==pp)continue;
if(!is_v[t]){
dfs(t,i,k);
if(!usdfa[t])deg[k]++;
else continue;
}
else if(!rs[i].is_tr)
deg[k]++;
if(ls){
ans.push_back(ANS(ls,k,t));
rs[lstid ].is_des= rs[lstid^1].is_des= rs[i] .is_des= rs[i^1] .is_des=1;
ls=0;
}
else {
ls=t;
lstid=i;
}
}
if(pre==-1)return ;
if(deg[k]&1){
usdfa[k]=1;
if(ls!=0){
rs[pre ].is_des= rs[pre^1].is_des= rs[lstid].is_des= rs[lstid^1].is_des=1;
ans.push_back(ANS(pp,k,ls));
}
}
}
int main(){
int a,b;
//freopen("1.in","r",stdin);
memset(fl,-1,sizeof fl);
scanf("%d%d",&pn,&edn);
for(int i=1;i<=edn;i++){
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
for(int i=1;i<=pn;i++){
if(!is_v[i]){
dfs(i,-1,-1);
}
}
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++)
printf("%d %d %d\n",ans[i].f,ans[i].m,ans[i].t);
}
<题目链接>
序列神题。
用拓扑维护数之间的不变关系。
加上线段树优化建图。
没有过$QAQ$
说是上面的题,蒟蒻麦蒙在CF官网上翻了半天愣是没有……
结论题,答案就是所有边权之和(%%%出题人)
简单证明一番。
我们想要最大值,于是可以转化为经过最小值的次数最少。
于是把最小值的边经过一次并删除,分成两棵树。
对这两棵树分别进行上述操作就可以得到次小和次次小值。
重复上述操作。可以得出结论,所有的边只会被经过一次。
于是就结束了,至于代码,放一个也行……
#include <cstdio>
using namespace std;
long long pn,c,ans;
int main(){
scanf("%lld",&pn);
for(int i=1;i<pn;i++){
scanf("%*d%*d%lld",&c);
ans+=c;
}
printf("%lld\n",ans);
}
时间分配还可以,T3分得有点少了。
所以T3的dp跪了。
|
25
|
860郭本一 | 50
03:11:03
|
5
03:11:03
|
11
03:13:31
|
66
03:13:31
|
话说$T2$为啥作差不加绝对值啊……
给题解留个坑$\Huge \lfloor\rfloor$
标签:void 最大 class clu space floor string end style
原文地址:https://www.cnblogs.com/kalginamiemeng/p/Exam20191005-07.html