if(true){ I love it }
轉載地址:https://my.oschina.net/elain/blog/382494
一、什麼是 AOP
AOP(Aspect-OrientedProgramming,面向切面程式設計),可以說是OOP(Object-Oriented Programing,面向物件程式設計)的補充和完善。OOP引入封裝、繼承和多型性等概念來建立一種物件層次結構,用以模擬公共行為的一個集合。當我們需要為分散的物件引入公共行為(日誌、安全、事務)的時候,OOP則顯得無能為力。也就是說,OOP允許你定義從上到下的關係,但並不適合定義從左到右的關係。例如日誌功能。日誌程式碼往往水平地散佈在所有物件層次中,而與它所散佈到的物件的核心功能毫無關係。對於其他型別的程式碼,如安全性、異常處理和透明的持續性也是如此。這種散佈在各處的無關的程式碼被稱為橫切(cross-cutting)程式碼,在OOP設計中,它導致了大量程式碼的重複,模組間的藕合度高,而不利於各個模組的重用。
而AOP技術則恰恰相反,它利用一種稱為“橫切”的技術,剖解開封裝的物件內部,並將那些影響了多個類的公共行為封裝到一個可重用模組,並將其名為“Aspect”,即切面。所謂“切面”,簡單地說,就是將那些與業務無關,卻為業務模組所共同呼叫的邏輯或責任封裝起來,便於減少系統的重複程式碼,降低模組間的耦合度,並有利於未來的可操作性和可維護性。AOP代表的是一個橫向的關係,如果說“物件”是一個空心的圓柱體,其中封裝的是物件的屬性和行為;那麼面向方面程式設計的方法,就彷彿一把利刃,將這些空心圓柱體剖開,以獲得其內部的訊息。而剖開的切面,也就是所謂的“方面”了。然後它又以巧奪天功的妙手將這些剖開的切面復原,不留痕跡。
使用“橫切”技術,AOP把軟體系統分為兩個部分:核心業務邏輯元件和橫切關注點。橫切關注點模組化為特殊的類,這些類被稱為“切面”,好處:1.橫切關注點都集中於一塊,不會出現大量重複程式碼;2.核心模組只關注核心功能的程式碼,模組間藕合度降低。
二、AOP 的實現原理
如圖:AOP 實際上是由目標類的代理類實現的。AOP 代理其實是由 AOP 框架動態生成的一個物件,該物件可作為目標物件使用。AOP 代理包含了目標物件的全部方法,但 AOP 代理中的方法與目標物件的方法存在差異,AOP 方法在特定切入點添加了增強處理,並回調了目標物件的方法。
三、AOP相關概念
連線點(Joinpoint
通知(Advice):在切面的某個特定的連線點上執行的動作。其中包括了“around”、“before”和“after”等不同型別的通知(通知的型別將在後面部分進行討論)。許多AOP框架(包括Spring)都是以攔截器做通知模型,並維護一個以連線點為中心的攔截器鏈。
切入點(Pointcut):匹配連線點的斷言。通知和一個切入點表示式關聯,並在滿足這個切入點的連線點上執行(例如,當執行某個特定名稱的方法時)。切入點表示式如何和連線點匹配是AOP的核心:Spring預設使用AspectJ切入點語法。
引入(Introduction):用來給一個型別宣告額外的方法或屬性(也被稱為連線型別宣告(inter-type declaration))。Spring允許引入新的介面(以及一個對應的實現)到任何被代理的物件。例如,你可以使用引入來使一個bean實現IsModified介面,以便簡化快取機制。
織入(Weaving):將切面應用到目標物件來建立新的代理物件的過程。這些可以在編譯時(例如使用AspectJ編譯器),類載入時和執行時完成。Spring和其他純Java AOP框架一樣,在執行時完成織入。
增強(Advice):是織入到目標類連線點上的一段程式程式碼。Spring使用增強類定義橫切邏輯,同時由於Spring只支援方法連線點,增強還包括了在方法上的哪一點加入橫切程式碼的方位資訊,所以增強既包括橫切邏輯、還包含部分連線點的資訊。
引介(Introduction):是一種特殊的增強,為類新增一些屬性和方法。
切面(Advisor):代表一般切面,包含了橫切程式碼和連線點資訊,本身是一個簡單的切面,橫切的連線點是目標類的所有方法。3種類型:一般切面(advisor)、切點切面(PointcutAdvisor)、引介切面(IntroductionAdvisor)。
四、Spring中AOP的實現
第一種是基於xml配置檔案方式的實現,
第二種是基於註解方式的實現。
首先我們來看一下業務邏輯service層:
/**
* RegisterService的實現類
* @author 曹勝歡 */
public class RegisterServiceImpl implements RegisterService {
private RegisterDao registerDao;
public RegisterServiceImpl() {}
/** 帶引數的構造方法 */
public RegisterServiceImpl(RegisterDao registerDao){
this.registerDao =registerDao;
}
public void save(String loginname, String password) {
registerDao.save(loginname, password);
throw new RuntimeException("故意丟擲一個異常。。。。");
}
/** set方法 */
public void setRegisterDao(RegisterDao registerDao) {
this.registerDao = registerDao;
}}
對於業務系統來說,RegisterServiceImpl類就是目標實現類,它的業務方法,如save()方法的前後或程式碼會出現異常的地方都是AOP的連線點。
下面是日誌服務類的程式碼:
/**
* 日誌切面類
* @author 曹勝歡
*/
public class LogAspect {
//任何通知方法都可以將第一個引數定義為 org.aspectj.lang.JoinPoint型別
public void before(JoinPoint call) {
//獲取目標物件對應的類名
String className = call.getTarget().getClass().getName();
//獲取目標物件上正在執行的方法名
String methodName = call.getSignature().getName();
System.out.println("前置通知:" + className + "類的" + methodName + "方法開始了");
}
public void afterReturn() {
System.out.println("後置通知:方法正常結束了");
}
public void after(){
System.out.println("最終通知:不管方法有沒有正常執行完成,一定會返回的");
}
public void afterThrowing() {
System.out.println("異常丟擲後通知:方法執行時出異常了");
}
//用來做環繞通知的方法可以第一個引數定義為org.aspectj.lang.ProceedingJoinPoint型別
public Object doAround(ProceedingJoinPoint call) throws Throwable {
Object result = null;
this.before(call);//相當於前置通知
try {
result = call.proceed();
this.afterReturn(); //相當於後置通知
} catch (Throwable e) {
this.afterThrowing(); //相當於異常丟擲後通知
throw e;
}finally{
this.after(); //相當於最終通知
}
return result;
}
}
這個類屬於業務服務類,如果用AOP的術語來說,它就是一個切面類,它定義了許多通知。Before()、afterReturn()、after()和afterThrowing()這些方法都是通知。
下面我們就來看具體配置,首先來看一下:
<1>.基於xml配置檔案的AOP實現:這種方式在實現AOP時,有4個步驟。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd>
<bean id="registerDaoImpl" class="com.zxf.dao.RegisterDaoImpl"/>
<bean id="registerService" class="com.zxf.service.RegisterServiceImpl">
<property name=" registerDaoImpl " ref=" RegisterDaoImpl "/>
</bean>
<!-- 日誌切面類 -->
<bean id="logAspectBean" class="com.zxf.aspect.LogAspect"/>
<!-- 第1步: AOP的配置 -->
<aop:config>
<!-- 第2步:配置一個切面 -->
<aop:aspect id="logAspect" ref="logAspectBean">
<!-- 第3步:定義切入點,指定切入點表示式 -->
<aop:pointcut id="allMethod"
expression="execution(* com.zxf.service.*.*(..))"/>
<!-- 第4步:應用前置通知 -->
<aop:before method="before" pointcut-ref="allMethod" />
<!-- 第4步:應用後置通知 -->
<aop:after-returning method="afterReturn" pointcut-ref="allMethod"/>
<!-- 第4步:應用最終通知 -->
<aop:after method="after" pointcut-ref="allMethod"/>
<!-- 第4步:應用丟擲異常後通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="allMethod"/>
<!-- 第4步:應用環繞通知 -->
<!--
<aop:around method="doAround" pointcut-ref="allMethod" />
-->
</aop:aspect>
</aop:config>
</beans>
上述配置針對切入點應用了前置、後置、最終,以及丟擲異常後通知。這樣在測試執行RegisterServiceImpl類的save()方法時,控制檯會有如下結果輸出:
前置通知:com.zxf.service.RegisterServiceImpl類的save方法開始了。
針對MySQL的RegisterDao實現中的save()方法。
後置通知:方法正常結束了。
最終通知:不管方法有沒有正常執行完成,一定會返回的。
下面我們在來看一下第二種配置方式:
<2>基於註解的AOP的實現
首先建立一個用來作為切面的類LogAnnotationAspect,同時把這個類配置在spring的配置檔案中。
在spring2.0以後引入了JDK5.0的註解Annotation的支援,提供了對AspectJ基於註解的切面的支援,從而 更進一步地簡化AOP的配置。具體的步驟有兩步。
Spring的配置檔案是如下的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd>
<bean id="registerDao" class="com.zxf.dao.RegisterDaoImpl"/>
<bean id="registerService" class="com.zxf.service.RegisterServiceImpl">
<property name="registerDao" ref="registerDao"/>
</bean>
<!-- 把切面類交由Spring容器來管理 -->
<bean id="logAspectBean" class="com.zxf.aspect.LogAnnotationAspect"/>
<!-- 啟用spring對AspectJ註解的支援 -->
<aop:aspectj-autoproxy/>
</beans>
這是那個切面的類LogAnnotationAspect
/**
* 日誌切面類
*/
@Aspect //定義切面類
public class LogAnnotationAspect {
@SuppressWarnings("unused")
//定義切入點,提供一個方法,這個方法的名字就是改切入點的id
@Pointcut("execution(* com.zxf.service.*.*(..))")
private void allMethod(){}
//針對指定的切入點表示式選擇的切入點應用前置通知
@Before("execution(* com. zxf.service.*.*(..))")
public void before(JoinPoint call) {
String className = call.getTarget().getClass().getName();
String methodName = call.getSignature().getName();
System.out.println("【註解-前置通知】:" + className + "類的"
+ methodName + "方法開始了");
}
//訪問命名切入點來應用後置通知
@AfterReturning("allMethod()")
public void afterReturn() {
System.out.println("【註解-後置通知】:方法正常結束了");
}
//應用最終通知
@After("allMethod()")
public void after(){
System.out.println("【註解-最終通知】:不管方法有沒有正常執行完成,"
+ "一定會返回的");
}
//應用異常丟擲後通知
@AfterThrowing("allMethod()")
public void afterThrowing() {
System.out.println("【註解-異常丟擲後通知】:方法執行時出異常了");
}
//應用周圍通知
//@Around("allMethod()")
public Object doAround(ProceedingJoinPoint call) throws Throwable{
Object result = null;
this.before(call);//相當於前置通知
try {
result = call.proceed();
this.afterReturn(); //相當於後置通知
} catch (Throwable e) {
this.afterThrowing(); //相當於異常丟擲後通知
throw e;
}finally{
this.after(); //相當於最終通知
}
return result;
}
}
五:Spring中AOP的兩種代理方式(Java動態代理和CGLIB代理)
Spring AOP使用動態代理技術在執行期織入增強程式碼。使用兩種代理機制:基於JDK的動態代理(JDK本身只提供介面的代理);基於CGlib的動態代理。
1. JDK的動態代理主要涉及java.lang.reflect包中的兩個類:Proxy和InvocationHandler。其中InvocationHandler只是一個介面,可以通過實現該介面定義橫切邏輯,並通過反射機制呼叫目標類的程式碼,動態的將橫切邏輯與業務邏輯織在一起。而Proxy利用InvocationHandler動態建立一個符合某一介面的例項,生成目標類的代理物件。(只能為介面建立代理例項)
//需要被代理的介面
public interface ForumService {
public void removeTopic(int topicId);
public void removeForum(int forumId);
}
//被代理介面的實現類,包含核心的業務邏輯
public class ForumServiceImpl implements ForumService{
@Override
public void removeTopic(int topicId) {
System.out.println("模擬刪除Topic記錄:"+ topicId);
try {
Thread.currentThread().sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void removeForum(int forumId) {
System.out.println("模擬刪除Forum記錄:"+ forumId);
try {
Thread.currentThread().sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//效能監控核心程式碼生成
public class MethodPerformance {
private long begin;
private long end;
private String serviceMethod;
public MethodPerformance(String serviceMethod) {
this.serviceMethod = serviceMethod;
this.begin = System.currentTimeMillis();
};
public void printPerformance(){
this.end = System.currentTimeMillis();
long elapse = this.end - this.begin;
System.out.println(serviceMethod + " cost " + elapse +"ms");
}
}
//執行緒安全的橫切邏輯
public class PerformanceMonitor {
private static ThreadLocal<MethodPerformance> tl= new ThreadLocal<MethodPerformance>();
public static void begin(String method){
System.out.println("begin monitor");
MethodPerformance mp = new MethodPerformance(method);
tl.set(mp);
}
public static void end(){
System.out.println("end monitor");
MethodPerformance mp = tl.get();
mp.printPerformance();
}
}
//AOP橫切模組
public class PerfermanceHandler implements InvocationHandler{
private Object target;
public PerfermanceHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
PerformanceMonitor.begin(target.getClass().getName()+"."+method.getName());
Object object = method.invoke(target, args);
PerformanceMonitor.end();
return object;
}
}
//測試
public class TestForumService {
public static void main(String[] args) {
ForumService target = new ForumServiceImpl();
//將目標業務類與橫切程式碼編織到一起
PerfermanceHandler handler = new PerfermanceHandler(target);
//建立代理例項
ForumService proxy = (ForumService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), handler);
proxy.removeForum(10);
proxy.removeTopic(1012);
}
}
begin monitor
模擬刪除Forum記錄:10
end monitor
com.baobaotao.proxy.ForumServiceImpl.removeForum cost 42ms
begin monitor
模擬刪除Topic記錄:1012
end monitor
com.baobaotao.proxy.ForumServiceImpl.removeTopic cost 21ms
2.CGLib採用底層的位元組碼技術,為一個類建立子類,並在子類中採用方法攔截的技術攔截所有父類的呼叫方法,並順勢織入橫切邏輯。
package com.baobaotao.proxy;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
enhancer.setSuperclass(clazz);//設定建立子類的類
enhancer.setCallback(this);
return enhancer.create();//通過位元組碼技術動態建立子類例項
}
@Override
public Object intercept(Object target, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
PerformanceMonitor.begin(target.getClass().getName()+"."+method.getName());
Object object = proxy.invokeSuper(target, args);
PerformanceMonitor.end();
return object;
}
}
package com.baobaotao.proxy;
import java.lang.reflect.Proxy;
//測試
public class TestForumService {
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
ForumServiceImpl service = (ForumServiceImpl) cglibProxy.getProxy(ForumServiceImpl.class);
service.removeForum(10);
service.removeTopic(1012);
}
}
begin monitor
模擬刪除Forum記錄:10
end monitor
com.baobaotao.proxy.ForumServiceImpl$$EnhancerByCGLIB$$626e31f5(子類).removeForum cost 67ms
begin monitor
模擬刪除Topic記錄:1012
end monitor
com.baobaotao.proxy.ForumServiceImpl$$EnhancerByCGLIB$$626e31f5.removeTopic cost 20ms
Spring增強類
Spring支援5種增強型別:
1)前置增強:org.springframework.aop.BeforeAdvice代表前置增強,spring只支援方法級的增強,目前可用MethodBeforeAdvice。
public interface Waiter {
public void greetTo(String name);
public void serveTo(String name);
}
public class NaiveWaiter implements Waiter {
@Override
public void greetTo(String name) {
System.out.println("greetTo "+ name +"...");
}
@Override
public void serveTo(String name) {
System.out.println("serveTo "+ name +"...");
}
}
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class GreeteBeforeAdvice implements MethodBeforeAdvice{
@Override
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
String client = (String) arg1[0];
System.out.println("How are you!"+client+".");
}
}
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
public class TestBeforeAdvice {
public static void main(String[] args) {
Waiter target = new NaiveWaiter();
BeforeAdvice advice = new GreeteBeforeAdvice();
//Spring提供的代理工廠
ProxyFactory pf = new ProxyFactory();//使用Cglib2AOPProx 即CGlib代理技術建立代理
// pf.setInterfaces(target.getClass().getInterfaces());//使用JdkDynamicAopProxy
//設定代理目標
pf.setTarget(target);
//新增增強處理
pf.addAdvice(advice);
//生成代理例項
Waiter waiter = (Waiter) pf.getProxy();
waiter.greetTo("Tom");
waiter.serveTo("Lucy");
// ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
// Waiter waiter1 = (Waiter) ctx.getBean("waiter");
// waiter1.greetTo("John");
}
}
<bean id="target" class="com.baobaotao.advice.NaiveWaiter" />
<bean id="greeteAdvice" class="com.baobaotao.advice.GreeteBeforeAdvice" />
<bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.baobaotao.advice.Waiter" p:interceptorNames="greeteAdvice"
p:target-ref="target" />
2)後置增強:org.springframework.aop.AfterReturningAdvice代表後置增強,在目標方法執行後實施增強。
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class GreeteAfterAdvice implements AfterReturningAdvice{
@Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
System.out.println("Please enjoy yourself!");
}
}
<bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.baobaotao.advice.Waiter" p:interceptorNames="greeteBefore,greeteAfter"
p:target-ref="target" />
3)環繞增強:org.aopalliance.intercept.MethodInterceptor代表環繞增強,在目標方法執行前後實施增強。
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class GreeteInterceptor implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation inv) throws Throwable {
Object[] args = inv.getArguments();
String client = (String) args[0];
System.out.println("How are you!"+client+".");
Object obj = inv.proceed();
System.out.println("Please enjoy yourself!");
return obj;
}
}
4)異常丟擲增強:org.springframework.aop.ThrowsAdvice,在目標方法執行丟擲異常後實施增強。方法名必須為afterThrowing,如參前三個可選,最後一個是Throwable或其子類。
import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
public class TransactionManager implements ThrowsAdvice {
public void afterThrowing(Method method, Object[] args, Object target,
Exception ex) throws Throwable {
System.out.println("-----------");
System.out.println("method:" + method.getName());
System.out.println("丟擲異常:" + ex.getMessage());
System.out.println("成功回滾事務。");
}
}
5)引介增強:org.springframework.aop.IntroductionInterceptor,表示目標類新增一些新的方法和屬性,連線點是類級別,而不是方法級別。
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
import com.baobaotao.proxy.PerformanceMonitor;
public class ControllablePerformaceMonitor extends DelegatingIntroductionInterceptor implements Monitorable{
private ThreadLocal<Boolean> MonitorStatusMap = new ThreadLocal<Boolean>();
@Override
public void setMonitorActive(boolean active) {
MonitorStatusMap.set(active);
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object obj = null;
if (MonitorStatusMap.get() != null && MonitorStatusMap.get()) {
PerformanceMonitor.begin(mi.getClass().getName() + "."
+ mi.getMethod().getName());
obj = super.invoke(mi);
PerformanceMonitor.end();
} else {
obj = super.invoke(mi);
}
return obj;
}
}
<bean id="forumService" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interfaces="com.baobaotao.introduce.Monitorable" //引入引介增強要實現的介面
p:target-ref="forumServiceTarget"
p:interceptorNames="pmonitor"
p:proxyTargetClass="true" />//只能通過為目標型別類建立子類的方式生成增強的代理
AOP切面的配置方式
1)基於Schema的配置:在xml中描述切點、增強型別,切面類為pojo
2)基於AspectJ的配置:切點、增強型別使用註解進行描述
相關推薦
【if(true){ I love it }】留下積累的每一份知識
專欄達人 授予成功建立個人部落格專欄
if(true){ I love it }
轉載地址:https://my.oschina.net/elain/blog/382494 一、什麼是 AOP AOP(Aspect-OrientedProgramming,面向切面程式設計),可以說是OOP(Object-Oriented Programing,面向物件
[HDU1754]I Hate It線段樹裸題
getc har namespace getch div names tchar c++ 定義 http://acm.hdu.edu.cn/showproblem.php?pid=1754 解題關鍵:剛開始死活超時,最後發現竟然是ch,和t1、t2每次循環都定義的鍋,以後
hdu1754 I Hate It
chm 學校 pda ott main update ron hdu1754 其中 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。這讓很多學生很反感。不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序,模擬老師的詢問。當然,
hdu 1754 I Hate It 線段樹 點改動
dsm time opc stdin sca fun iostream nim mini // hdu 1754 I Hate It 線段樹 點改動 // // 不多說,裸的點改動 // // 繼續練 #include <algorithm> #includ
[HDOJ1754]I Hate It(分塊)
using cnblogs names eof sca 鏈接 include ons code 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 題意:老題了,現場賽總是有很多題,雖然想不到正解,但是服務器都比較勁,用分
HDU 1754 I Hate it (線段樹最大值模板)
mod algorithm font 求和 span space eof reat data- 思路:與我發表的上一遍求和的思想一樣 僅僅是如今變成求最大值而已 AC代碼: #include<iostream> #include<cstdio>
HDU 1754 I Hate It<區間最值 單點修改>
des div 分數 流行 esc ble lin problems php I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota
hdu1754 I hate it (線段樹)
文件 build dash ota pan pos 最大 eps track I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot
POJ 1678 I Love this Game
first 先行者 logs 最大差值 sin return algo pre sstream 題目鏈接:http://poj.org/problem?id=1678 動態博弈。用dp[i]來表示如果先行者首先選擇第i個數字的話能取得的最大差值。由於每次選擇的數字一定比上一
HDU - 1754 I Hate It (線段樹區間求最值)
clas lan () esp tdi typedef show scanf ons 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 題意:線段樹的單點更新和區間求最值 模板題,,,???,, 1 #in
【線段樹】I Hate It
程序 printf 處理 其中 bmi ott 學生 ref 兩個 I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub
HDU-1754 I Hate It(線段樹、點變化+段查詢---模板)
區間 printf desc d+ ++ pda ava des mission I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot
HDU1754 I HATE IT【線段樹】
hdu1754 一個 比較 har space 文件 include 分數 程序 題面: Problem Description 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。 這讓很多學生很反感。 不管你喜不喜歡,現在需要你做的是,就是
J - I Hate It HDU - 1754
out 成績 tree 同學 treenode 線段樹 stdio.h temp 測試的 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。 這讓很多學生很反感。 不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序,模擬老師的詢
HDU - 1754 I Hate It
std names 模擬 hint blog style while cout pac 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。 這讓很多學生很反感。 不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序,模擬老師的
HDU 1754: I Hate It
define date author -s for i hate it using lin http ///@author Sycamore///@date 9/17/2017///@link http://acm.hdu.edu.cn/showproblem.php?pi
I hate it [HDU 1754]
一行 pretty tchar processor turn 復雜 一次 pda ace 題目描述 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。 這讓很多學生很反感。不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序
B - I Hate It
har pan tex fff iostream fin space 16px nta B - I Hate It HDU - 1754 思路:線段樹板子。 #include<cstdio> #include<cstri
洛谷 P1531 I Hate It
需要 namespace 字符 ref str 現在 .org build blog P1531 I Hate It 題目背景 很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。這讓很多學生很反感。 題目描述 不管你喜不喜歡,現在需要你做的是